├── .gitignore ├── vs2008 ├── .gitignore ├── SDMMCAnalyzer.sln └── SDMMCAnalyzer.vcproj ├── xcode4 ├── .gitignore └── SDMMCAnalyzer.xcodeproj │ └── project.pbxproj ├── src ├── SDMMCHelpers.h ├── SDMMCAnalyzerResults.h ├── SDMMCSimulationDataGenerator.h ├── SDMMCAnalyzerSettings.h ├── SDMMCAnalyzer.h ├── SDMMCAnalyzerSettings.cpp ├── SDMMCSimulationDataGenerator.cpp ├── SDMMCHelpers.cpp ├── SDMMCAnalyzer.cpp └── SDMMCAnalyzerResults.cpp ├── LICENSE.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.gitignore 3 | debug/ 4 | release/ 5 | -------------------------------------------------------------------------------- /vs2008/.gitignore: -------------------------------------------------------------------------------- 1 | Debug 2 | Release 3 | *.ncb 4 | *.suo 5 | *.vcproj.*.user 6 | -------------------------------------------------------------------------------- /xcode4/.gitignore: -------------------------------------------------------------------------------- 1 | SDMMCAnalyzer.xcodeproj/project.xcworkspace 2 | SDMMCAnalyzer.xcodeproj/xcuserdata 3 | build 4 | -------------------------------------------------------------------------------- /src/SDMMCHelpers.h: -------------------------------------------------------------------------------- 1 | #ifndef __SDMMC_HELPERS 2 | #define __SDMMC_HELPERS 3 | 4 | #include 5 | 6 | enum MMCResponseType { 7 | MMC_RSP_NONE, 8 | MMC_RSP_R1, 9 | MMC_RSP_R2_CID, 10 | MMC_RSP_R2_CSD, 11 | MMC_RSP_R3, 12 | MMC_RSP_R4, 13 | MMC_RSP_R5, 14 | }; 15 | 16 | struct MMCResponse 17 | { 18 | enum MMCResponseType mType; 19 | unsigned int mBits; 20 | int mTimeout; 21 | bool mBusy; 22 | }; 23 | 24 | class SDMMCHelpers 25 | { 26 | public: 27 | 28 | public: 29 | static U8 crc7(const U8 *data, unsigned int size); 30 | static struct MMCResponse MMCCommandResponse(unsigned int index); 31 | 32 | private: 33 | static U8 __crc7(U8 crc, U8 data); 34 | static U8 __crc7_finalize(U8 crc); 35 | }; 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /vs2008/SDMMCAnalyzer.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual C++ Express 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDMMCAnalyzer", "SDMMCAnalyzer.vcproj", "{D7556E7E-A6BF-4BCE-BDC8-E66D2874C301}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {D7556E7E-A6BF-4BCE-BDC8-E66D2874C301}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {D7556E7E-A6BF-4BCE-BDC8-E66D2874C301}.Debug|Win32.Build.0 = Debug|Win32 14 | {D7556E7E-A6BF-4BCE-BDC8-E66D2874C301}.Release|Win32.ActiveCfg = Release|Win32 15 | {D7556E7E-A6BF-4BCE-BDC8-E66D2874C301}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /src/SDMMCAnalyzerResults.h: -------------------------------------------------------------------------------- 1 | #ifndef __SDMMC_ANALYZER_RESULTS 2 | #define __SDMMC_ANALYZER_RESULTS 3 | 4 | #include 5 | 6 | class SDMMCAnalyzer; 7 | class SDMMCAnalyzerSettings; 8 | 9 | class SDMMCAnalyzerResults : public AnalyzerResults 10 | { 11 | public: 12 | SDMMCAnalyzerResults(SDMMCAnalyzer* analyzer, SDMMCAnalyzerSettings* settings); 13 | virtual ~SDMMCAnalyzerResults(); 14 | virtual void GenerateBubbleText(U64 frame_index, Channel& channel, DisplayBase display_base ); 15 | virtual void GenerateExportFile(const char* file, DisplayBase display_base, U32 export_type_user_id); 16 | virtual void GenerateFrameTabularText(U64 frame_index, DisplayBase display_base); 17 | virtual void GeneratePacketTabularText(U64 packet_id, DisplayBase display_base); 18 | virtual void GenerateTransactionTabularText(U64 transaction_id, DisplayBase display_base); 19 | 20 | public: 21 | enum FrameType { 22 | FRAMETYPE_HEADER, 23 | FRAMETYPE_COMMAND, 24 | FRAMETYPE_RESPONSE, 25 | FRAMETYPE_CRC, 26 | }; 27 | 28 | protected: 29 | SDMMCAnalyzerSettings *mSettings; 30 | SDMMCAnalyzer *mAnalyzer; 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/SDMMCSimulationDataGenerator.h: -------------------------------------------------------------------------------- 1 | #ifndef __SDMMC_SIMULATION_DATA_GENERATOR 2 | #define __SDMMC_SIMULATION_DATA_GENERATOR 3 | 4 | #include 5 | #include 6 | 7 | class SDMMCAnalyzerSettings; 8 | struct SDMMCRequest; 9 | 10 | class SDMMCSimulationDataGenerator 11 | { 12 | public: 13 | SDMMCSimulationDataGenerator(); 14 | ~SDMMCSimulationDataGenerator(); 15 | 16 | void Initialize(U32 simulation_sample_rate, SDMMCAnalyzerSettings *settings); 17 | U32 GenerateSimulationData(U64 newest_sample_requested, U32 sample_rate, SimulationChannelDescriptor **channels); 18 | 19 | protected: 20 | void CreateClockPeriod(); 21 | void CreateIdle(double seconds); 22 | void CreateCommand(unsigned int index, unsigned long arg); 23 | void CreateResponse48(unsigned int index, unsigned long arg); 24 | 25 | protected: 26 | SDMMCAnalyzerSettings *mSettings; 27 | 28 | U32 mSimulationSampleRateHz; 29 | ClockGenerator mClockGenerator; 30 | 31 | SimulationChannelDescriptorGroup mChannels; 32 | SimulationChannelDescriptor *mClock; 33 | SimulationChannelDescriptor *mCommand; 34 | }; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Dirk Hörner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/SDMMCAnalyzerSettings.h: -------------------------------------------------------------------------------- 1 | #ifndef __SDMMC_ANALYZER_SETTINGS 2 | #define __SDMMC_ANALYZER_SETTINGS 3 | 4 | #include 5 | #include 6 | 7 | enum SDMMCProtocol { 8 | PROTOCOL_MMC, 9 | PROTOCOL_SD, 10 | }; 11 | 12 | enum SDMMCSampleEdge { 13 | SAMPLE_EDGE_RISING, 14 | SAMPLE_EDGE_FALLING 15 | }; 16 | 17 | class SDMMCAnalyzerSettings : public AnalyzerSettings 18 | { 19 | public: 20 | SDMMCAnalyzerSettings(); 21 | virtual ~SDMMCAnalyzerSettings(); 22 | 23 | virtual bool SetSettingsFromInterfaces(); 24 | void UpdateInterfacesFromSettings(); 25 | 26 | virtual void LoadSettings(const char *settings); 27 | virtual const char *SaveSettings(); 28 | 29 | Channel mClockChannel; 30 | Channel mCommandChannel; 31 | enum SDMMCProtocol mProtocol; 32 | enum SDMMCSampleEdge mSampleEdge; 33 | 34 | protected: 35 | std::auto_ptr mClockChannelInterface; 36 | std::auto_ptr mCommandChannelInterface; 37 | std::auto_ptr mProtocolInterface; 38 | std::auto_ptr mSampleEdgeInterface; 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/SDMMCAnalyzer.h: -------------------------------------------------------------------------------- 1 | #ifndef __SDMMC_ANALYZER_H 2 | #define __SDMMC_ANALYZER_H 3 | 4 | #include 5 | #include "SDMMCAnalyzerSettings.h" 6 | #include "SDMMCAnalyzerResults.h" 7 | #include "SDMMCSimulationDataGenerator.h" 8 | #include "SDMMCAnalyzer.h" 9 | #include "SDMMCHelpers.h" 10 | 11 | class ANALYZER_EXPORT SDMMCAnalyzer : public Analyzer 12 | { 13 | public: 14 | static const char Name[]; 15 | 16 | public: 17 | SDMMCAnalyzer(); 18 | virtual ~SDMMCAnalyzer(); 19 | 20 | virtual const char *GetAnalyzerName() const; 21 | 22 | virtual void WorkerThread(); 23 | virtual bool NeedsRerun(); 24 | 25 | virtual U32 GenerateSimulationData( U64 newest_sample_requested, U32 sample_rate, SimulationChannelDescriptor** simulation_channels ); 26 | virtual U32 GetMinimumSampleRateHz(); 27 | 28 | protected: 29 | void AdvanceToNextClock(); 30 | int TryReadCommand(); 31 | int WaitForAndReadMMCResponse(struct MMCResponse response); 32 | 33 | protected: 34 | std::auto_ptr mSettings; 35 | std::auto_ptr mResults; 36 | 37 | SDMMCSimulationDataGenerator mDataGenerator; 38 | bool mSimulationInitialized; 39 | 40 | AnalyzerChannelData *mClock; 41 | AnalyzerChannelData *mCommand; 42 | }; 43 | 44 | extern "C" ANALYZER_EXPORT const char* __cdecl GetAnalyzerName(); 45 | extern "C" ANALYZER_EXPORT Analyzer* __cdecl CreateAnalyzer( ); 46 | extern "C" ANALYZER_EXPORT void __cdecl DestroyAnalyzer( Analyzer* analyzer ); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SD/MMC Analyzer for Logic 2 | ========================= 3 | 4 | This implements an SD/MMC protocol analyzer for Logic (http://www.saleae.com). 5 | 6 | Compiling 7 | --------- 8 | 9 | In order to compile the code the Saleae Analyzer SDK is needed which can be download via the Saleae Community pages (http://www.saleae.com/community/). The code is tested against version 1.1.9 of the SDK. 10 | 11 | Prior to compiling the SDK zip file should be unpacked into the directory containing the cloned sdmmc-analyzer repository, e.g.: 12 | 13 | +-rootdir/ 14 | +-SaleaeAnalyzerSdk-1.1.9/ 15 | +-sdmmc-analyzer/ 16 | 17 | ### Mac OS X 18 | 19 | Use the Xode project in xcode4/. 20 | 21 | ### Linux 22 | 23 | run ./build_analyzer.py 24 | 25 | ### Windows 26 | 27 | Not yet supported 28 | 29 | Debugging 30 | --------- 31 | 32 | ### Mac OS X 33 | 34 | * Configure Xcode to place build products in locations specified by targets 35 | * Xcode -> Preferences -> Locations Tab -> Build Location 36 | * Edit SDMMCAnalyzer Scheme to launch Logic upon debugging 37 | * Product -> Edit Scheme -> Debug -> Info -> Executable 38 | * Browse for Logic.app (e.g. /Applications/Logic.app) 39 | * Configure Logic to look for the Analyzer Plugin 40 | * Launch Logic manually 41 | * Options -> Preferences 42 | * Under [For Developers], "Search this path for Analyzer Plugins" 43 | * Browse for the ../sdmmc-analyzer/xcode4/build/Debug directory 44 | * Click "Save" and close Logic 45 | 46 | -------------------------------------------------------------------------------- /src/SDMMCAnalyzerSettings.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "SDMMCAnalyzerSettings.h" 3 | 4 | SDMMCAnalyzerSettings::SDMMCAnalyzerSettings() 5 | : mClockChannel(UNDEFINED_CHANNEL), 6 | mCommandChannel(UNDEFINED_CHANNEL), 7 | mProtocol(PROTOCOL_MMC), 8 | mSampleEdge(SAMPLE_EDGE_RISING) 9 | { 10 | mClockChannelInterface.reset(new AnalyzerSettingInterfaceChannel()); 11 | mClockChannelInterface->SetTitleAndTooltip("Clock", "Clock (CLK)"); 12 | mClockChannelInterface->SetChannel(mClockChannel); 13 | 14 | mCommandChannelInterface.reset(new AnalyzerSettingInterfaceChannel()); 15 | mCommandChannelInterface->SetTitleAndTooltip("Command", "Command (CMD)"); 16 | mCommandChannelInterface->SetChannel(mCommandChannel); 17 | 18 | mProtocolInterface.reset(new AnalyzerSettingInterfaceNumberList()); 19 | mProtocolInterface->SetTitleAndTooltip("Protocol", "Protocol"); 20 | mProtocolInterface->AddNumber(PROTOCOL_MMC, "MMC", "MMC protocol"); 21 | mProtocolInterface->AddNumber(PROTOCOL_SD, "SD", "SD protocol"); 22 | mProtocolInterface->SetNumber(mProtocol); 23 | 24 | mSampleEdgeInterface.reset(new AnalyzerSettingInterfaceNumberList()); 25 | mSampleEdgeInterface->SetTitleAndTooltip("Sample edge", "Clock sampling edge"); 26 | mSampleEdgeInterface->AddNumber(SAMPLE_EDGE_RISING, "Rising", "Sample on rising edge"); 27 | mSampleEdgeInterface->AddNumber(SAMPLE_EDGE_FALLING, "Falling", "Sample on falling edge"); 28 | mSampleEdgeInterface->SetNumber(mSampleEdge); 29 | 30 | AddInterface(mClockChannelInterface.get()); 31 | AddInterface(mCommandChannelInterface.get()); 32 | AddInterface(mProtocolInterface.get()); 33 | AddInterface(mSampleEdgeInterface.get()); 34 | 35 | ClearChannels(); 36 | AddChannel(mClockChannel, "Clock", false); 37 | AddChannel(mCommandChannel, "Command", false); 38 | } 39 | 40 | SDMMCAnalyzerSettings::~SDMMCAnalyzerSettings() 41 | { 42 | } 43 | 44 | bool SDMMCAnalyzerSettings::SetSettingsFromInterfaces() 45 | { 46 | Channel clk = mClockChannelInterface->GetChannel(); 47 | Channel cmd = mCommandChannelInterface->GetChannel(); 48 | 49 | if (clk == cmd) { 50 | SetErrorText("Please select different channels for each input."); 51 | return false; 52 | } 53 | 54 | mClockChannel = clk; 55 | mCommandChannel = cmd; 56 | mProtocol = SDMMCProtocol((U32)mProtocolInterface->GetNumber()); 57 | mSampleEdge = SDMMCSampleEdge((U32)mSampleEdgeInterface->GetNumber()); 58 | 59 | ClearChannels(); 60 | AddChannel(mClockChannel, "Clock", true); 61 | AddChannel(mCommandChannel, "Command", true); 62 | 63 | return true; 64 | } 65 | 66 | void SDMMCAnalyzerSettings::UpdateInterfacesFromSettings() 67 | { 68 | mClockChannelInterface->SetChannel(mClockChannel); 69 | mCommandChannelInterface->SetChannel(mCommandChannel); 70 | mProtocolInterface->SetNumber(mProtocol); 71 | mSampleEdgeInterface->SetNumber(mSampleEdge); 72 | } 73 | 74 | void SDMMCAnalyzerSettings::LoadSettings(const char *settings) 75 | { 76 | SimpleArchive archive; 77 | U32 tmp; 78 | 79 | archive.SetString(settings); 80 | 81 | archive >> mClockChannel; 82 | archive >> mCommandChannel; 83 | archive >> tmp; mProtocol = SDMMCProtocol(tmp); 84 | archive >> tmp; mSampleEdge = SDMMCSampleEdge(tmp); 85 | 86 | ClearChannels(); 87 | AddChannel(mClockChannel, "Clock", true); 88 | AddChannel(mCommandChannel, "Command", true); 89 | 90 | UpdateInterfacesFromSettings(); 91 | } 92 | 93 | const char *SDMMCAnalyzerSettings::SaveSettings() 94 | { 95 | SimpleArchive archive; 96 | 97 | archive << mClockChannel; 98 | archive << mCommandChannel; 99 | archive << mProtocol; 100 | archive << mSampleEdge; 101 | 102 | return SetReturnString(archive.GetString()); 103 | } 104 | -------------------------------------------------------------------------------- /src/SDMMCSimulationDataGenerator.cpp: -------------------------------------------------------------------------------- 1 | #include "SDMMCSimulationDataGenerator.h" 2 | #include "SDMMCAnalyzerSettings.h" 3 | #include "SDMMCHelpers.h" 4 | 5 | SDMMCSimulationDataGenerator::SDMMCSimulationDataGenerator() 6 | { 7 | } 8 | 9 | SDMMCSimulationDataGenerator::~SDMMCSimulationDataGenerator() 10 | { 11 | } 12 | 13 | void SDMMCSimulationDataGenerator::Initialize(U32 simulation_sample_rate, SDMMCAnalyzerSettings *settings) 14 | { 15 | mSimulationSampleRateHz = simulation_sample_rate; 16 | mSettings = settings; 17 | 18 | mClockGenerator.Init(400000, mSimulationSampleRateHz); 19 | 20 | mClock = mChannels.Add(mSettings->mClockChannel, mSimulationSampleRateHz, BIT_HIGH); 21 | mCommand = mChannels.Add(mSettings->mCommandChannel, mSimulationSampleRateHz, BIT_HIGH); 22 | 23 | /* introduce a few periods of no clock */ 24 | mChannels.AdvanceAll(mClockGenerator.AdvanceByHalfPeriod(10.0)); 25 | } 26 | 27 | U32 SDMMCSimulationDataGenerator::GenerateSimulationData(U64 newest_sample_requested, U32 sample_rate, SimulationChannelDescriptor **channels) 28 | { 29 | U64 adjusted_newest_sample_requested = AnalyzerHelpers::AdjustSimulationTargetSample( newest_sample_requested, sample_rate, mSimulationSampleRateHz ); 30 | 31 | while (mClock->GetCurrentSampleNumber() < adjusted_newest_sample_requested) { 32 | CreateIdle(0.1); 33 | CreateCommand(0, 0); 34 | CreateIdle(0.01); 35 | CreateCommand(1, 0); 36 | CreateResponse48(1, 0x00FF8000); 37 | CreateIdle(0.01); 38 | CreateCommand(1, 0x40300000); 39 | CreateResponse48(1, 0x80FF8000); 40 | } 41 | 42 | *channels = mChannels.GetArray(); 43 | return mChannels.GetCount(); 44 | } 45 | 46 | void SDMMCSimulationDataGenerator::CreateClockPeriod() 47 | { 48 | mClock->Transition(); 49 | mChannels.AdvanceAll(mClockGenerator.AdvanceByHalfPeriod(.5)); 50 | 51 | mClock->Transition(); 52 | mChannels.AdvanceAll(mClockGenerator.AdvanceByHalfPeriod(.5)); 53 | } 54 | 55 | void SDMMCSimulationDataGenerator::CreateIdle(double seconds) 56 | { 57 | U64 samples = (U64)(400000.0 * seconds); 58 | U64 orig = mClock->GetCurrentSampleNumber(); 59 | 60 | while ((mClock->GetCurrentSampleNumber() - orig) < samples) { 61 | CreateClockPeriod(); 62 | } 63 | } 64 | 65 | void SDMMCSimulationDataGenerator::CreateCommand(unsigned int index, unsigned long arg) 66 | { 67 | U64 data = 68 | (0ull << 39) | /* start bit */ 69 | (1ull << 38) | /* transmission bit: host */ 70 | ((U64)index << 32) | /* command index */ 71 | ((U64)arg << 0); /* command argument */ 72 | 73 | /* make sure we continue with clock as high */ 74 | if (mClock->GetCurrentBitState() != BIT_HIGH) { 75 | mClock->Transition(); 76 | mChannels.AdvanceAll(mClockGenerator.AdvanceByHalfPeriod(.5)); 77 | } 78 | 79 | BitExtractor bits(data, AnalyzerEnums::MsbFirst, 40); 80 | 81 | for (int i = 0; i < 40; i++) { 82 | mCommand->TransitionIfNeeded(bits.GetNextBit()); 83 | CreateClockPeriod(); 84 | } 85 | 86 | /* FIXME: ugly, only works on little-endian */ 87 | U8 crc = SDMMCHelpers::crc7((U8 *)&data, 5); 88 | 89 | for (int i = 0; i < 7; i++) { 90 | crc <<= 1; 91 | 92 | mCommand->TransitionIfNeeded(crc & 0x80 ? BIT_HIGH : BIT_LOW); 93 | CreateClockPeriod(); 94 | } 95 | 96 | /* stop bit */ 97 | mCommand->TransitionIfNeeded(BIT_HIGH); 98 | CreateClockPeriod(); 99 | } 100 | 101 | void SDMMCSimulationDataGenerator::CreateResponse48(unsigned int index, unsigned long arg) 102 | { 103 | U64 data = 104 | (0ull << 39) | /* start bit */ 105 | (0ull << 38) | /* transmission bit: host */ 106 | ((U64)index << 32) | /* command index */ 107 | ((U64)arg << 0); /* command argument */ 108 | 109 | /* make sure we continue with clock as high */ 110 | if (mClock->GetCurrentBitState() != BIT_HIGH) { 111 | mClock->Transition(); 112 | mChannels.AdvanceAll(mClockGenerator.AdvanceByHalfPeriod(.5)); 113 | } 114 | 115 | CreateClockPeriod(); 116 | CreateClockPeriod(); 117 | 118 | BitExtractor bits(data, AnalyzerEnums::MsbFirst, 40); 119 | 120 | for (int i = 0; i < 40; i++) { 121 | mCommand->TransitionIfNeeded(bits.GetNextBit()); 122 | CreateClockPeriod(); 123 | } 124 | 125 | /* FIXME: ugly, only works on little-endian */ 126 | U8 crc = SDMMCHelpers::crc7((U8 *)&data, 5); 127 | 128 | for (int i = 0; i < 7; i++) { 129 | crc <<= 1; 130 | 131 | mCommand->TransitionIfNeeded(crc & 0x80 ? BIT_HIGH : BIT_LOW); 132 | CreateClockPeriod(); 133 | } 134 | 135 | /* stop bit */ 136 | mCommand->TransitionIfNeeded(BIT_HIGH); 137 | CreateClockPeriod(); 138 | } 139 | -------------------------------------------------------------------------------- /src/SDMMCHelpers.cpp: -------------------------------------------------------------------------------- 1 | #include "SDMMCHelpers.h" 2 | 3 | static struct MMCResponse responses[64] = { 4 | /* 0 */ {MMC_RSP_NONE, 0, 0, false}, 5 | /* 1 */ {MMC_RSP_R3, 32, 5, false}, 6 | /* 2 */ {MMC_RSP_R2_CID, 128, 5, false}, 7 | /* 3 */ {MMC_RSP_R1, 32, 64, false}, 8 | /* 4 */ {MMC_RSP_NONE, 0, 0, false}, 9 | /* 5 */ {MMC_RSP_R1, 32, 64, true}, 10 | /* 6 */ {MMC_RSP_R1, 32, 64, true}, 11 | /* 7 */ {MMC_RSP_R1, 32, 64, true}, 12 | /* 8 */ {MMC_RSP_R1, 32, 64, false}, 13 | /* 9 */ {MMC_RSP_R2_CSD, 128, 64, false}, 14 | /* 10 */ {MMC_RSP_R2_CID, 128, 64, false}, 15 | /* 11 */ {MMC_RSP_R1, 32, 64, false}, 16 | /* 12 */ {MMC_RSP_R1, 32, 64, false}, 17 | /* 13 */ {MMC_RSP_R1, 32, 64, false}, 18 | /* 14 */ {MMC_RSP_R1, 32, 64, false}, 19 | /* 15 */ {MMC_RSP_NONE, 0, 0, false}, 20 | /* 16 */ {MMC_RSP_R1, 32, 64, false}, 21 | /* 17 */ {MMC_RSP_R1, 32, 64, false}, 22 | /* 18 */ {MMC_RSP_R1, 32, 64, false}, 23 | /* 19 */ {MMC_RSP_R1, 32, 64, false}, 24 | /* 20 */ {MMC_RSP_R1, 32, 64, false}, 25 | /* 21 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 26 | /* 22 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 27 | /* 23 */ {MMC_RSP_R1, 32, 64, false}, 28 | /* 24 */ {MMC_RSP_R1, 32, 64, false}, 29 | /* 25 */ {MMC_RSP_R1, 32, 64, false}, 30 | /* 26 */ {MMC_RSP_R1, 32, 64, false}, 31 | /* 27 */ {MMC_RSP_R1, 32, 64, false}, 32 | /* 28 */ {MMC_RSP_R1, 32, 64, true}, 33 | /* 29 */ {MMC_RSP_R1, 32, 64, true}, 34 | /* 30 */ {MMC_RSP_R1, 32, 64, false}, 35 | /* 31 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 36 | /* 32 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 37 | /* 33 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 38 | /* 34 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 39 | /* 35 */ {MMC_RSP_R1, 32, 64, false}, 40 | /* 36 */ {MMC_RSP_R1, 32, 64, false}, 41 | /* 37 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 42 | /* 38 */ {MMC_RSP_R1, 32, 64, true}, 43 | /* 39 */ {MMC_RSP_R4, 32, 64, false}, 44 | /* 40 */ {MMC_RSP_R5, 32, 64, false}, 45 | /* 41 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 46 | /* 42 */ {MMC_RSP_R1, 32, 64, false}, 47 | /* 43 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 48 | /* 44 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 49 | /* 45 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 50 | /* 46 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 51 | /* 47 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 52 | /* 48 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 53 | /* 49 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 54 | /* 50 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 55 | /* 51 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 56 | /* 52 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 57 | /* 53 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 58 | /* 54 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 59 | /* 55 */ {MMC_RSP_R1, 32, 64, false}, 60 | /* 56 */ {MMC_RSP_R1, 32, 64, false}, 61 | /* 57 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 62 | /* 58 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 63 | /* 59 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 64 | /* 60 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 65 | /* 61 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 66 | /* 62 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 67 | /* 63 */ {MMC_RSP_NONE, 0, 0, false}, /* reserved */ 68 | }; 69 | 70 | static struct MMCResponse invalid_response = { 71 | MMC_RSP_NONE, 0, 0, false 72 | }; 73 | 74 | U8 SDMMCHelpers::crc7(const U8 *data, unsigned int size) 75 | { 76 | U8 crc = 0; 77 | 78 | for (unsigned int i = 0; i < size; i++) { 79 | crc = __crc7(crc, *data); 80 | data++; 81 | } 82 | 83 | return __crc7_finalize(crc); 84 | } 85 | 86 | struct MMCResponse SDMMCHelpers::MMCCommandResponse(unsigned int index) 87 | { 88 | if (index > 63) 89 | return invalid_response; 90 | 91 | return responses[index]; 92 | } 93 | 94 | /* 95 | * fast crc7 sd/mmc implementation taken from: 96 | * http://catid.mechafetus.com/news/news.php?view=253 97 | */ 98 | 99 | U8 SDMMCHelpers::__crc7(U8 crc, U8 data) 100 | { 101 | data ^= crc << 1; 102 | 103 | if (data & 0x80) 104 | data ^= 9; 105 | 106 | crc = data ^ (crc & 0x78) ^ (crc << 4) ^ ((crc >> 3) & 0x0f); 107 | 108 | return crc & 0x7f; 109 | } 110 | 111 | U8 SDMMCHelpers::__crc7_finalize(U8 crc) 112 | { 113 | crc = (crc << 1) ^ (crc << 4) ^ (crc & 0x70) ^ ((crc >> 3) & 0x0f); 114 | return crc | 1; 115 | } 116 | -------------------------------------------------------------------------------- /vs2008/SDMMCAnalyzer.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 26 | 29 | 32 | 35 | 38 | 41 | 53 | 56 | 59 | 62 | 71 | 74 | 77 | 80 | 83 | 86 | 89 | 92 | 93 | 101 | 104 | 107 | 110 | 113 | 116 | 128 | 131 | 134 | 137 | 148 | 151 | 154 | 157 | 160 | 163 | 166 | 169 | 170 | 171 | 172 | 173 | 174 | 179 | 182 | 183 | 186 | 187 | 190 | 191 | 194 | 195 | 198 | 199 | 202 | 203 | 206 | 207 | 210 | 211 | 214 | 215 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | -------------------------------------------------------------------------------- /src/SDMMCAnalyzer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "SDMMCAnalyzer.h" 3 | #include "SDMMCAnalyzerResults.h" 4 | #include "SDMMCHelpers.h" 5 | 6 | const char SDMMCAnalyzer::Name[] = "SDMMC"; 7 | 8 | SDMMCAnalyzer::SDMMCAnalyzer() 9 | : Analyzer(), 10 | mSettings(new SDMMCAnalyzerSettings()), 11 | mSimulationInitialized(false) 12 | { 13 | SetAnalyzerSettings(mSettings.get()); 14 | } 15 | 16 | SDMMCAnalyzer::~SDMMCAnalyzer() 17 | { 18 | KillThread(); 19 | } 20 | 21 | const char* SDMMCAnalyzer::GetAnalyzerName() const 22 | { 23 | return Name; 24 | } 25 | 26 | void SDMMCAnalyzer::WorkerThread() 27 | { 28 | mResults.reset(new SDMMCAnalyzerResults(this, mSettings.get())); 29 | SetAnalyzerResults(mResults.get()); 30 | 31 | mResults->AddChannelBubblesWillAppearOn(mSettings->mCommandChannel); 32 | 33 | mClock = GetAnalyzerChannelData(mSettings->mClockChannel); 34 | mCommand = GetAnalyzerChannelData(mSettings->mCommandChannel); 35 | 36 | while (true) { 37 | int cmdindex; 38 | 39 | ReportProgress(mClock->GetSampleNumber()); 40 | CheckIfThreadShouldExit(); 41 | AdvanceToNextClock(); 42 | 43 | cmdindex = TryReadCommand(); 44 | if (cmdindex < 0) { 45 | /* continue if parsing the command failed */ 46 | continue; 47 | } 48 | 49 | if (mSettings->mProtocol == PROTOCOL_MMC) { 50 | struct MMCResponse response = SDMMCHelpers::MMCCommandResponse(cmdindex); 51 | if (response.mType != MMC_RSP_NONE) 52 | WaitForAndReadMMCResponse(response); 53 | } else { 54 | /* FIXME: implement SD response handling */ 55 | } 56 | } 57 | } 58 | 59 | bool SDMMCAnalyzer::NeedsRerun() 60 | { 61 | return false; 62 | } 63 | 64 | U32 SDMMCAnalyzer::GenerateSimulationData(U64 newest_sample_requested, U32 sample_rate, SimulationChannelDescriptor** simulation_channels) 65 | { 66 | if (!mSimulationInitialized) { 67 | mDataGenerator.Initialize(GetSimulationSampleRate(), mSettings.get()); 68 | mSimulationInitialized = true; 69 | } 70 | 71 | return mDataGenerator.GenerateSimulationData(newest_sample_requested, sample_rate, simulation_channels); 72 | } 73 | 74 | U32 SDMMCAnalyzer::GetMinimumSampleRateHz() 75 | { 76 | return 400000 * 4; 77 | } 78 | 79 | void SDMMCAnalyzer::AdvanceToNextClock() 80 | { 81 | enum BitState search = mSettings->mSampleEdge == SAMPLE_EDGE_RISING ? BIT_HIGH : BIT_LOW; 82 | 83 | do { 84 | mClock->AdvanceToNextEdge(); 85 | } while (mClock->GetBitState() != search); 86 | 87 | mCommand->AdvanceToAbsPosition(mClock->GetSampleNumber()); 88 | } 89 | 90 | int SDMMCAnalyzer::TryReadCommand() 91 | { 92 | int index; 93 | 94 | /* check for start bit */ 95 | if (mCommand->GetBitState() != BIT_LOW) 96 | return -1; 97 | 98 | mResults->AddMarker(mClock->GetSampleNumber(), AnalyzerResults::Start, mSettings->mCommandChannel); 99 | AdvanceToNextClock(); 100 | 101 | /* transfer bit */ 102 | if (mCommand->GetBitState() != BIT_HIGH) { 103 | /* if host is not transferring this is no command */ 104 | mResults->AddMarker(mClock->GetSampleNumber(), AnalyzerResults::X, mSettings->mCommandChannel); 105 | return -1; 106 | } 107 | AdvanceToNextClock(); 108 | 109 | /* command index and argument */ 110 | { 111 | Frame frame; 112 | 113 | frame.mStartingSampleInclusive = mClock->GetSampleNumber(); 114 | frame.mData1 = 0; 115 | frame.mData2 = 0; 116 | frame.mType = SDMMCAnalyzerResults::FRAMETYPE_COMMAND; 117 | 118 | for (int i = 0; i < 6; i++) { 119 | frame.mData1 = (frame.mData1 << 1) | mCommand->GetBitState(); 120 | AdvanceToNextClock(); 121 | } 122 | 123 | for (int i = 0; i < 32; i++) { 124 | frame.mData2 = (frame.mData2 << 1) | mCommand->GetBitState(); 125 | AdvanceToNextClock(); 126 | } 127 | 128 | frame.mEndingSampleInclusive = mClock->GetSampleNumber() - 1; 129 | mResults->AddFrame(frame); 130 | 131 | /* save index for returning */ 132 | index = (int)frame.mData1; 133 | } 134 | 135 | /* crc */ 136 | { 137 | Frame frame; 138 | 139 | frame.mStartingSampleInclusive = mClock->GetSampleNumber(); 140 | frame.mData1 = 0; 141 | frame.mType = SDMMCAnalyzerResults::FRAMETYPE_CRC; 142 | 143 | for (int i = 0; i < 7; i++) { 144 | frame.mData1 = (frame.mData1 << 1) | mCommand->GetBitState(); 145 | AdvanceToNextClock(); 146 | } 147 | 148 | frame.mEndingSampleInclusive = mClock->GetSampleNumber() - 1; 149 | mResults->AddFrame(frame); 150 | } 151 | 152 | /* stop bit */ 153 | mResults->AddMarker(mClock->GetSampleNumber(), AnalyzerResults::Stop, mSettings->mCommandChannel); 154 | 155 | mResults->CommitResults(); 156 | ReportProgress(mClock->GetSampleNumber()); 157 | 158 | return index; 159 | } 160 | 161 | int SDMMCAnalyzer::WaitForAndReadMMCResponse(struct MMCResponse response) 162 | { 163 | int timeout = response.mTimeout + 3; // add some slack time 164 | 165 | while (timeout-- >= 0 && mCommand->GetBitState() != BIT_LOW) 166 | AdvanceToNextClock(); 167 | 168 | if (timeout < 0) 169 | return -1; 170 | 171 | mResults->AddMarker(mClock->GetSampleNumber(), AnalyzerResults::Start, mSettings->mCommandChannel); 172 | AdvanceToNextClock(); 173 | 174 | /* transfer bit */ 175 | if (mCommand->GetBitState() != BIT_LOW) { 176 | /* if card is not transferring this is no response */ 177 | mResults->AddMarker(mClock->GetSampleNumber(), AnalyzerResults::X, mSettings->mCommandChannel); 178 | return -1; 179 | } 180 | AdvanceToNextClock(); 181 | 182 | /* skip 6 bits */ 183 | for (int i = 0; i < 6; i++) 184 | AdvanceToNextClock(); 185 | 186 | /* response */ 187 | { 188 | Frame frame; 189 | 190 | frame.mStartingSampleInclusive = mClock->GetSampleNumber(); 191 | frame.mData1 = 0; 192 | frame.mData2 = 0; 193 | frame.mType = SDMMCAnalyzerResults::FRAMETYPE_RESPONSE; 194 | frame.mFlags = response.mType; 195 | 196 | int bits = response.mBits; 197 | 198 | for (int i = 0; i < 64 && bits > 0; i++, bits--) { 199 | frame.mData1 = (frame.mData1 << 1) | mCommand->GetBitState(); 200 | AdvanceToNextClock(); 201 | } 202 | 203 | for (int i = 0; i < 64 && bits > 0; i++, bits--) { 204 | frame.mData2 = (frame.mData2 << 1) | mCommand->GetBitState(); 205 | AdvanceToNextClock(); 206 | } 207 | 208 | frame.mEndingSampleInclusive = mClock->GetSampleNumber() - 1; 209 | mResults->AddFrame(frame); 210 | } 211 | 212 | /* crc */ 213 | if (response.mType != MMC_RSP_R2_CID && response.mType != MMC_RSP_R2_CSD) { 214 | Frame frame; 215 | 216 | frame.mStartingSampleInclusive = mClock->GetSampleNumber(); 217 | frame.mData1 = 0; 218 | frame.mType = SDMMCAnalyzerResults::FRAMETYPE_CRC; 219 | 220 | for (int i = 0; i < 7; i++) { 221 | frame.mData1 = (frame.mData1 << 1) | mCommand->GetBitState(); 222 | AdvanceToNextClock(); 223 | } 224 | 225 | frame.mEndingSampleInclusive = mClock->GetSampleNumber() - 1; 226 | mResults->AddFrame(frame); 227 | } 228 | 229 | /* stop bit */ 230 | mResults->AddMarker(mClock->GetSampleNumber(), AnalyzerResults::Stop, mSettings->mCommandChannel); 231 | 232 | mResults->CommitResults(); 233 | ReportProgress(mClock->GetSampleNumber()); 234 | 235 | return 1; 236 | } 237 | 238 | /* 239 | * loader hooks 240 | */ 241 | 242 | const char* GetAnalyzerName() 243 | { 244 | return SDMMCAnalyzer::Name; 245 | } 246 | 247 | Analyzer* CreateAnalyzer() 248 | { 249 | return new SDMMCAnalyzer(); 250 | } 251 | 252 | void DestroyAnalyzer(Analyzer* analyzer) 253 | { 254 | delete analyzer; 255 | } 256 | -------------------------------------------------------------------------------- /src/SDMMCAnalyzerResults.cpp: -------------------------------------------------------------------------------- 1 | #include "SDMMCAnalyzerResults.h" 2 | #include "SDMMCAnalyzer.h" 3 | #include "SDMMCAnalyzerSettings.h" 4 | #include "SDMMCHelpers.h" 5 | 6 | SDMMCAnalyzerResults::SDMMCAnalyzerResults(SDMMCAnalyzer* analyzer, SDMMCAnalyzerSettings* settings) 7 | : AnalyzerResults(), 8 | mSettings(settings), 9 | mAnalyzer(analyzer) 10 | { 11 | } 12 | 13 | SDMMCAnalyzerResults::~SDMMCAnalyzerResults() 14 | { 15 | } 16 | 17 | void SDMMCAnalyzerResults::GenerateBubbleText(U64 frame_index, Channel& channel, DisplayBase display_base) 18 | { 19 | ClearResultStrings(); 20 | Frame frame = GetFrame(frame_index); 21 | 22 | switch (frame.mType) { 23 | case FRAMETYPE_HEADER: 24 | if (frame.mData1 == 1) 25 | AddResultString("Host sending"); 26 | else 27 | AddResultString("Card sending"); 28 | break; 29 | 30 | case FRAMETYPE_COMMAND: 31 | { 32 | char str_cmd[4]; 33 | char str_arg[33]; 34 | 35 | AnalyzerHelpers::GetNumberString(frame.mData1, Decimal, 6, str_cmd, sizeof(str_cmd)); 36 | AnalyzerHelpers::GetNumberString(frame.mData2, display_base, 32, str_arg, sizeof(str_arg)); 37 | 38 | AddResultString("CMD"); 39 | AddResultString("CMD", str_cmd); 40 | AddResultString("CMD", str_cmd, ", arg=", str_arg); 41 | break; 42 | } 43 | 44 | case FRAMETYPE_RESPONSE: 45 | { 46 | char str_32[33]; 47 | 48 | switch (frame.mFlags) { 49 | case MMC_RSP_R1: 50 | { 51 | const char *str_state = "reserved"; 52 | std::string str_flags(""); 53 | 54 | switch ((frame.mData1 >> 9) & 0xf) { 55 | case 0: str_state = "Idle"; break; 56 | case 1: str_state = "Ready"; break; 57 | case 2: str_state = "Ident"; break; 58 | case 3: str_state = "Stby"; break; 59 | case 4: str_state = "Tran"; break; 60 | case 5: str_state = "Data"; break; 61 | case 6: str_state = "Rcv"; break; 62 | case 7: str_state = "Prg"; break; 63 | case 8: str_state = "Dis"; break; 64 | case 9: str_state = "Btst"; break; 65 | case 10: str_state = "Slp "; break; 66 | } 67 | 68 | AnalyzerHelpers::GetNumberString(frame.mData1, display_base, 32, str_32, sizeof(str_32)); 69 | 70 | AddResultString("R1"); 71 | AddResultString("R1, ", str_state); 72 | AddResultString("R1, ", str_state, ", rsp=", str_32); 73 | 74 | if (frame.mData1 & (1 << 31)) 75 | str_flags += " ADDRESS_OUT_OF_RANGE"; 76 | if (frame.mData1 & (1 << 30)) 77 | str_flags += " ADDRESS_MISALIGN"; 78 | if (frame.mData1 & (1 << 29)) 79 | str_flags += " BLOCK_LEN_ERROR"; 80 | if (frame.mData1 & (1 << 28)) 81 | str_flags += " ERASE_SEQ_ERROR"; 82 | if (frame.mData1 & (1 << 27)) 83 | str_flags += " ERASE_PARAM"; 84 | if (frame.mData1 & (1 << 26)) 85 | str_flags += " WP_VIOLATION"; 86 | if (frame.mData1 & (1 << 25)) 87 | str_flags += " CARD_IS_LOCKED"; 88 | if (frame.mData1 & (1 << 24)) 89 | str_flags += " LOCK_UNLOCK_FAILED"; 90 | if (frame.mData1 & (1 << 23)) 91 | str_flags += " COM_CRC_ERROR"; 92 | if (frame.mData1 & (1 << 22)) 93 | str_flags += " ILLEGAL_COMMAND"; 94 | if (frame.mData1 & (1 << 21)) 95 | str_flags += " CARD_ECC_FAILED"; 96 | if (frame.mData1 & (1 << 20)) 97 | str_flags += " CC_ERROR"; 98 | if (frame.mData1 & (1 << 19)) 99 | str_flags += " ERROR"; 100 | if (frame.mData1 & (1 << 18)) 101 | str_flags += " UNDERRUN"; 102 | if (frame.mData1 & (1 << 17)) 103 | str_flags += " OVERRUN"; 104 | if (frame.mData1 & (1 << 16)) 105 | str_flags += " CID/CSD_OVERWRITE"; 106 | if (frame.mData1 & (1 << 15)) 107 | str_flags += " WP_ERASE_SKIP"; 108 | if (frame.mData1 & (1 << 13)) 109 | str_flags += " ERASE_RESET"; 110 | if (frame.mData1 & (1 << 8)) 111 | str_flags += " READY_FOR_DATA"; 112 | if (frame.mData1 & (1 << 7)) 113 | str_flags += " SWITCH_ERROR"; 114 | if (frame.mData1 & (1 << 5)) 115 | str_flags += " APP_CMD"; 116 | 117 | if (str_flags.length() > 0) 118 | AddResultString("R1, ", str_state, ", rsp=", str_32, str_flags.c_str()); 119 | 120 | break; 121 | } 122 | case MMC_RSP_R2_CID: 123 | { 124 | std::string res("R2"); 125 | char pname[7], prv_str[4], psn_str[12]; 126 | char rsp_str[64]; 127 | 128 | AddResultString(res.c_str()); 129 | 130 | res += " [CID]"; 131 | AddResultString(res.c_str()); 132 | 133 | res += " rsp="; 134 | AnalyzerHelpers::GetNumberString(frame.mData1 >> 32, display_base, 32, rsp_str, sizeof(rsp_str)); 135 | res += rsp_str; 136 | res += " "; 137 | AnalyzerHelpers::GetNumberString(frame.mData1 & 0xffffffffull, display_base, 32, rsp_str, sizeof(rsp_str)); 138 | res += rsp_str; 139 | res += " "; 140 | AnalyzerHelpers::GetNumberString(frame.mData2 >> 32, display_base, 32, rsp_str, sizeof(rsp_str)); 141 | res += rsp_str; 142 | res += " "; 143 | AnalyzerHelpers::GetNumberString(frame.mData2 & 0xffffffffull, display_base, 32, rsp_str, sizeof(rsp_str)); 144 | res += rsp_str; 145 | AddResultString(res.c_str()); 146 | 147 | pname[0] = (frame.mData1 >> 32) & 0xff; 148 | pname[1] = (frame.mData1 >> 24) & 0xff; 149 | pname[2] = (frame.mData1 >> 16) & 0xff; 150 | pname[3] = (frame.mData1 >> 8) & 0xff; 151 | pname[4] = (frame.mData1 >> 0) & 0xff; 152 | pname[5] = (frame.mData2 >> 56) & 0xff; 153 | pname[6] = 0; 154 | 155 | unsigned prv = (unsigned)((frame.mData2 >> 48) & 0xff); 156 | prv_str[0] = '0' + ((prv >> 4) & 0x0f); 157 | prv_str[1] = '.'; 158 | prv_str[2] = '0' + (prv & 0x0f); 159 | prv_str[3] = 0; 160 | 161 | unsigned psn = (unsigned)((frame.mData2 >> 16) & 0xfffffffful); 162 | AnalyzerHelpers::GetNumberString(psn, Decimal, 32, psn_str, sizeof(psn_str)); 163 | 164 | res += " pnm='"; 165 | res += pname; 166 | res += "' prv="; 167 | res += prv_str; 168 | res += " psn="; 169 | res += psn_str; 170 | AddResultString(res.c_str()); 171 | 172 | break; 173 | } 174 | case MMC_RSP_R2_CSD: 175 | { 176 | std::string res("R2"); 177 | char rsp_str[64]; 178 | 179 | AddResultString(res.c_str()); 180 | 181 | res += " [CSD]"; 182 | AddResultString(res.c_str()); 183 | 184 | res += " rsp="; 185 | AnalyzerHelpers::GetNumberString(frame.mData1 >> 32, display_base, 32, rsp_str, sizeof(rsp_str)); 186 | res += rsp_str; 187 | res += " "; 188 | AnalyzerHelpers::GetNumberString(frame.mData1 & 0xffffffffull, display_base, 32, rsp_str, sizeof(rsp_str)); 189 | res += rsp_str; 190 | res += " "; 191 | AnalyzerHelpers::GetNumberString(frame.mData2 >> 32, display_base, 32, rsp_str, sizeof(rsp_str)); 192 | res += rsp_str; 193 | res += " "; 194 | AnalyzerHelpers::GetNumberString(frame.mData2 & 0xffffffffull, display_base, 32, rsp_str, sizeof(rsp_str)); 195 | res += rsp_str; 196 | AddResultString(res.c_str()); 197 | 198 | break; 199 | } 200 | case MMC_RSP_R3: 201 | AnalyzerHelpers::GetNumberString(frame.mData1, Hexadecimal, 32, str_32, sizeof(str_32)); 202 | AddResultString("R3"); 203 | AddResultString("R3, ocr=", str_32); 204 | break; 205 | case MMC_RSP_R4: 206 | AddResultString("R4"); 207 | break; 208 | case MMC_RSP_R5: 209 | AddResultString("R5"); 210 | break; 211 | } 212 | break; 213 | } 214 | 215 | case FRAMETYPE_CRC: 216 | { 217 | char str_crc[8]; 218 | 219 | AnalyzerHelpers::GetNumberString(frame.mData1, Hexadecimal, 7, str_crc, sizeof(str_crc)); 220 | 221 | AddResultString("CRC"); 222 | AddResultString("CRC=", str_crc); 223 | break; 224 | } 225 | 226 | default: 227 | AddResultString("error"); 228 | } 229 | } 230 | 231 | void SDMMCAnalyzerResults::GenerateExportFile(const char* file, DisplayBase display_base, U32 export_type_user_id) 232 | { 233 | ClearResultStrings(); 234 | AddResultString("not supported"); 235 | } 236 | 237 | void SDMMCAnalyzerResults::GenerateFrameTabularText(U64 frame_index, DisplayBase display_base) 238 | { 239 | ClearResultStrings(); 240 | AddResultString("not supported"); 241 | } 242 | 243 | void SDMMCAnalyzerResults::GeneratePacketTabularText(U64 packet_id, DisplayBase display_base) 244 | { 245 | ClearResultStrings(); 246 | AddResultString("not supported"); 247 | } 248 | 249 | void SDMMCAnalyzerResults::GenerateTransactionTabularText(U64 transaction_id, DisplayBase display_base) 250 | { 251 | ClearResultStrings(); 252 | AddResultString("not supported"); 253 | } 254 | -------------------------------------------------------------------------------- /xcode4/SDMMCAnalyzer.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 21052B1F13EC832F00B5A7C5 /* SDMMCAnalyzer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21052B1D13EC832F00B5A7C5 /* SDMMCAnalyzer.cpp */; }; 11 | 21052B2013EC832F00B5A7C5 /* SDMMCAnalyzer.h in Headers */ = {isa = PBXBuildFile; fileRef = 21052B1E13EC832F00B5A7C5 /* SDMMCAnalyzer.h */; }; 12 | 21052B2313EC84B200B5A7C5 /* libAnalyzer.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 21052B2213EC84B200B5A7C5 /* libAnalyzer.dylib */; }; 13 | 213D832213EC959600B01739 /* SDMMCAnalyzerSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 213D832013EC959600B01739 /* SDMMCAnalyzerSettings.cpp */; }; 14 | 213D832313EC959600B01739 /* SDMMCAnalyzerSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 213D832113EC959600B01739 /* SDMMCAnalyzerSettings.h */; }; 15 | 213D832613ECA1E700B01739 /* SDMMCSimulationDataGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 213D832413ECA1E700B01739 /* SDMMCSimulationDataGenerator.cpp */; }; 16 | 213D832713ECA1E700B01739 /* SDMMCSimulationDataGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 213D832513ECA1E700B01739 /* SDMMCSimulationDataGenerator.h */; }; 17 | 213D832C13EEF53600B01739 /* SDMMCAnalyzerResults.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 213D832A13EEF53500B01739 /* SDMMCAnalyzerResults.cpp */; }; 18 | 213D832D13EEF53600B01739 /* SDMMCAnalyzerResults.h in Headers */ = {isa = PBXBuildFile; fileRef = 213D832B13EEF53500B01739 /* SDMMCAnalyzerResults.h */; }; 19 | 213EA45F13EF3D2000D3CDF0 /* SDMMCHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 213EA45D13EF3D2000D3CDF0 /* SDMMCHelpers.cpp */; }; 20 | 213EA46013EF3D2000D3CDF0 /* SDMMCHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 213EA45E13EF3D2000D3CDF0 /* SDMMCHelpers.h */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 21052B1D13EC832F00B5A7C5 /* SDMMCAnalyzer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SDMMCAnalyzer.cpp; path = ../src/SDMMCAnalyzer.cpp; sourceTree = ""; }; 25 | 21052B1E13EC832F00B5A7C5 /* SDMMCAnalyzer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDMMCAnalyzer.h; path = ../src/SDMMCAnalyzer.h; sourceTree = ""; }; 26 | 21052B2213EC84B200B5A7C5 /* libAnalyzer.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libAnalyzer.dylib; path = "../../SaleaeAnalyzerSdk-1.1.9/lib/libAnalyzer.dylib"; sourceTree = ""; }; 27 | 213D832013EC959600B01739 /* SDMMCAnalyzerSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SDMMCAnalyzerSettings.cpp; path = ../src/SDMMCAnalyzerSettings.cpp; sourceTree = ""; }; 28 | 213D832113EC959600B01739 /* SDMMCAnalyzerSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDMMCAnalyzerSettings.h; path = ../src/SDMMCAnalyzerSettings.h; sourceTree = ""; }; 29 | 213D832413ECA1E700B01739 /* SDMMCSimulationDataGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SDMMCSimulationDataGenerator.cpp; path = ../src/SDMMCSimulationDataGenerator.cpp; sourceTree = ""; }; 30 | 213D832513ECA1E700B01739 /* SDMMCSimulationDataGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDMMCSimulationDataGenerator.h; path = ../src/SDMMCSimulationDataGenerator.h; sourceTree = ""; }; 31 | 213D832A13EEF53500B01739 /* SDMMCAnalyzerResults.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SDMMCAnalyzerResults.cpp; path = ../src/SDMMCAnalyzerResults.cpp; sourceTree = ""; }; 32 | 213D832B13EEF53500B01739 /* SDMMCAnalyzerResults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDMMCAnalyzerResults.h; path = ../src/SDMMCAnalyzerResults.h; sourceTree = ""; }; 33 | 213EA45D13EF3D2000D3CDF0 /* SDMMCHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SDMMCHelpers.cpp; path = ../src/SDMMCHelpers.cpp; sourceTree = ""; }; 34 | 213EA45E13EF3D2000D3CDF0 /* SDMMCHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDMMCHelpers.h; path = ../src/SDMMCHelpers.h; sourceTree = ""; }; 35 | 21BC295913EC826C00BA43C2 /* libSDMMCAnalyzer.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libSDMMCAnalyzer.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | /* End PBXFileReference section */ 37 | 38 | /* Begin PBXFrameworksBuildPhase section */ 39 | 21BC295613EC826C00BA43C2 /* Frameworks */ = { 40 | isa = PBXFrameworksBuildPhase; 41 | buildActionMask = 2147483647; 42 | files = ( 43 | 21052B2313EC84B200B5A7C5 /* libAnalyzer.dylib in Frameworks */, 44 | ); 45 | runOnlyForDeploymentPostprocessing = 0; 46 | }; 47 | /* End PBXFrameworksBuildPhase section */ 48 | 49 | /* Begin PBXGroup section */ 50 | 21052B2413EC84C000B5A7C5 /* Sources */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | 213D832013EC959600B01739 /* SDMMCAnalyzerSettings.cpp */, 54 | 213D832113EC959600B01739 /* SDMMCAnalyzerSettings.h */, 55 | 21052B1D13EC832F00B5A7C5 /* SDMMCAnalyzer.cpp */, 56 | 21052B1E13EC832F00B5A7C5 /* SDMMCAnalyzer.h */, 57 | 213D832A13EEF53500B01739 /* SDMMCAnalyzerResults.cpp */, 58 | 213D832B13EEF53500B01739 /* SDMMCAnalyzerResults.h */, 59 | 213EA45D13EF3D2000D3CDF0 /* SDMMCHelpers.cpp */, 60 | 213EA45E13EF3D2000D3CDF0 /* SDMMCHelpers.h */, 61 | 213D832413ECA1E700B01739 /* SDMMCSimulationDataGenerator.cpp */, 62 | 213D832513ECA1E700B01739 /* SDMMCSimulationDataGenerator.h */, 63 | ); 64 | name = Sources; 65 | sourceTree = ""; 66 | }; 67 | 21052B2513EC84D300B5A7C5 /* Libs */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 21052B2213EC84B200B5A7C5 /* libAnalyzer.dylib */, 71 | ); 72 | name = Libs; 73 | sourceTree = ""; 74 | }; 75 | 21BC294E13EC826B00BA43C2 = { 76 | isa = PBXGroup; 77 | children = ( 78 | 21052B2513EC84D300B5A7C5 /* Libs */, 79 | 21052B2413EC84C000B5A7C5 /* Sources */, 80 | 21BC295A13EC826C00BA43C2 /* Products */, 81 | ); 82 | sourceTree = ""; 83 | }; 84 | 21BC295A13EC826C00BA43C2 /* Products */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 21BC295913EC826C00BA43C2 /* libSDMMCAnalyzer.dylib */, 88 | ); 89 | name = Products; 90 | sourceTree = ""; 91 | }; 92 | /* End PBXGroup section */ 93 | 94 | /* Begin PBXHeadersBuildPhase section */ 95 | 21BC295713EC826C00BA43C2 /* Headers */ = { 96 | isa = PBXHeadersBuildPhase; 97 | buildActionMask = 2147483647; 98 | files = ( 99 | 21052B2013EC832F00B5A7C5 /* SDMMCAnalyzer.h in Headers */, 100 | 213D832313EC959600B01739 /* SDMMCAnalyzerSettings.h in Headers */, 101 | 213D832713ECA1E700B01739 /* SDMMCSimulationDataGenerator.h in Headers */, 102 | 213D832D13EEF53600B01739 /* SDMMCAnalyzerResults.h in Headers */, 103 | 213EA46013EF3D2000D3CDF0 /* SDMMCHelpers.h in Headers */, 104 | ); 105 | runOnlyForDeploymentPostprocessing = 0; 106 | }; 107 | /* End PBXHeadersBuildPhase section */ 108 | 109 | /* Begin PBXNativeTarget section */ 110 | 21BC295813EC826C00BA43C2 /* SDMMCAnalyzer */ = { 111 | isa = PBXNativeTarget; 112 | buildConfigurationList = 21BC295D13EC826C00BA43C2 /* Build configuration list for PBXNativeTarget "SDMMCAnalyzer" */; 113 | buildPhases = ( 114 | 21BC295513EC826C00BA43C2 /* Sources */, 115 | 21BC295613EC826C00BA43C2 /* Frameworks */, 116 | 21BC295713EC826C00BA43C2 /* Headers */, 117 | ); 118 | buildRules = ( 119 | ); 120 | dependencies = ( 121 | ); 122 | name = SDMMCAnalyzer; 123 | productName = SDMMCAnalyzer; 124 | productReference = 21BC295913EC826C00BA43C2 /* libSDMMCAnalyzer.dylib */; 125 | productType = "com.apple.product-type.library.dynamic"; 126 | }; 127 | /* End PBXNativeTarget section */ 128 | 129 | /* Begin PBXProject section */ 130 | 21BC295013EC826B00BA43C2 /* Project object */ = { 131 | isa = PBXProject; 132 | attributes = { 133 | ORGANIZATIONNAME = "DSP Group Inc."; 134 | }; 135 | buildConfigurationList = 21BC295313EC826C00BA43C2 /* Build configuration list for PBXProject "SDMMCAnalyzer" */; 136 | compatibilityVersion = "Xcode 3.2"; 137 | developmentRegion = English; 138 | hasScannedForEncodings = 0; 139 | knownRegions = ( 140 | en, 141 | ); 142 | mainGroup = 21BC294E13EC826B00BA43C2; 143 | productRefGroup = 21BC295A13EC826C00BA43C2 /* Products */; 144 | projectDirPath = ""; 145 | projectRoot = ""; 146 | targets = ( 147 | 21BC295813EC826C00BA43C2 /* SDMMCAnalyzer */, 148 | ); 149 | }; 150 | /* End PBXProject section */ 151 | 152 | /* Begin PBXSourcesBuildPhase section */ 153 | 21BC295513EC826C00BA43C2 /* Sources */ = { 154 | isa = PBXSourcesBuildPhase; 155 | buildActionMask = 2147483647; 156 | files = ( 157 | 21052B1F13EC832F00B5A7C5 /* SDMMCAnalyzer.cpp in Sources */, 158 | 213D832213EC959600B01739 /* SDMMCAnalyzerSettings.cpp in Sources */, 159 | 213D832613ECA1E700B01739 /* SDMMCSimulationDataGenerator.cpp in Sources */, 160 | 213D832C13EEF53600B01739 /* SDMMCAnalyzerResults.cpp in Sources */, 161 | 213EA45F13EF3D2000D3CDF0 /* SDMMCHelpers.cpp in Sources */, 162 | ); 163 | runOnlyForDeploymentPostprocessing = 0; 164 | }; 165 | /* End PBXSourcesBuildPhase section */ 166 | 167 | /* Begin XCBuildConfiguration section */ 168 | 21BC295B13EC826C00BA43C2 /* Debug */ = { 169 | isa = XCBuildConfiguration; 170 | buildSettings = { 171 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 172 | GCC_C_LANGUAGE_STANDARD = gnu99; 173 | GCC_OPTIMIZATION_LEVEL = 0; 174 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG; 175 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 176 | GCC_VERSION = 4.2; 177 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 178 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 179 | GCC_WARN_UNUSED_VARIABLE = YES; 180 | HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../SaleaeAnalyzerSdk-1.1.9/include"; 181 | MACOSX_DEPLOYMENT_TARGET = 10.6; 182 | ONLY_ACTIVE_ARCH = YES; 183 | SDKROOT = macosx; 184 | }; 185 | name = Debug; 186 | }; 187 | 21BC295C13EC826C00BA43C2 /* Release */ = { 188 | isa = XCBuildConfiguration; 189 | buildSettings = { 190 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 191 | GCC_C_LANGUAGE_STANDARD = gnu99; 192 | GCC_VERSION = 4.2; 193 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 194 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 195 | GCC_WARN_UNUSED_VARIABLE = YES; 196 | HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../SaleaeAnalyzerSdk-1.1.9/include"; 197 | MACOSX_DEPLOYMENT_TARGET = 10.6; 198 | SDKROOT = macosx; 199 | }; 200 | name = Release; 201 | }; 202 | 21BC295E13EC826C00BA43C2 /* Debug */ = { 203 | isa = XCBuildConfiguration; 204 | buildSettings = { 205 | ALWAYS_SEARCH_USER_PATHS = NO; 206 | COPY_PHASE_STRIP = NO; 207 | EXECUTABLE_PREFIX = lib; 208 | GCC_DYNAMIC_NO_PIC = NO; 209 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 210 | LIBRARY_SEARCH_PATHS = ( 211 | "$(inherited)", 212 | "\"$(SRCROOT)/../../SaleaeAnalyzerSdk-1.1.9/lib\"", 213 | ); 214 | PRODUCT_NAME = "$(TARGET_NAME)"; 215 | SDKROOT = macosx; 216 | }; 217 | name = Debug; 218 | }; 219 | 21BC295F13EC826C00BA43C2 /* Release */ = { 220 | isa = XCBuildConfiguration; 221 | buildSettings = { 222 | ALWAYS_SEARCH_USER_PATHS = NO; 223 | COPY_PHASE_STRIP = YES; 224 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 225 | EXECUTABLE_PREFIX = lib; 226 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 227 | LIBRARY_SEARCH_PATHS = ( 228 | "$(inherited)", 229 | "\"$(SRCROOT)/../../SaleaeAnalyzerSdk-1.1.9/lib\"", 230 | ); 231 | PRODUCT_NAME = "$(TARGET_NAME)"; 232 | SDKROOT = macosx; 233 | }; 234 | name = Release; 235 | }; 236 | /* End XCBuildConfiguration section */ 237 | 238 | /* Begin XCConfigurationList section */ 239 | 21BC295313EC826C00BA43C2 /* Build configuration list for PBXProject "SDMMCAnalyzer" */ = { 240 | isa = XCConfigurationList; 241 | buildConfigurations = ( 242 | 21BC295B13EC826C00BA43C2 /* Debug */, 243 | 21BC295C13EC826C00BA43C2 /* Release */, 244 | ); 245 | defaultConfigurationIsVisible = 0; 246 | defaultConfigurationName = Release; 247 | }; 248 | 21BC295D13EC826C00BA43C2 /* Build configuration list for PBXNativeTarget "SDMMCAnalyzer" */ = { 249 | isa = XCConfigurationList; 250 | buildConfigurations = ( 251 | 21BC295E13EC826C00BA43C2 /* Debug */, 252 | 21BC295F13EC826C00BA43C2 /* Release */, 253 | ); 254 | defaultConfigurationIsVisible = 0; 255 | defaultConfigurationName = Release; 256 | }; 257 | /* End XCConfigurationList section */ 258 | }; 259 | rootObject = 21BC295013EC826B00BA43C2 /* Project object */; 260 | } 261 | --------------------------------------------------------------------------------