CONTENT ======= 1 License 2 Purpose 3 SSM2 Protocol Overview 4 Platforms 5 Dependencies 6 Compilation 7 Contribute 8 Implementation Notes 9 Links 1) License ========== GPL3. See text file COPYING.txt for details. 2) Purpose ========== LibSSM2 is a .NET library providing functionality for the SSM2 (Subaru Select Monitor 2) protocol. Most importantly the packet classes know how to create and parse SSM2 packets. The consumer code therefore can concentrate on the payload data itself. Currently 8 out of 10 well known SSM2 packet types are implemented in the code. Although there are several OSS projects using SSM2 internally, I did not like most implementations and/or the additional work required for filtering out the actual SSM2 protocol stuff. So I wrote my own code from scratch the way I think it should be - implented as a lean independent library. To actually make use of this library you'll need an appropriate hardware interface (typically standard OBD-II port on the car, serial or USB port for computer) plus additional code and knowledge in order to send and receive data (in the form of SSM2 packets) via interface. Application code using this library has been tested with several hardware interfaces on various operating systems. Sooner or later, depending on spare time, I will also publish application code. 3) SSM2 Protocol Overview ========================= SSM2 is a special car diagnostic protocol. For details see text file SSM2_Protocol.txt. As far as I know it is only being used by Subaru (c) cars. Subaru is a trademark of Fuji Heavy Industries Ltd (FHI). SSM2 operates at 4800 baud and is being used by (original) Subaru cars from 2001+ (?). Earlier models may use SSM1, a very different protocol, using 1953 baud. 4) Platforms ============ The code is platform independent pure C#, compliant with the Common Language Specification (CLS). Originally created with MonoDevelop on Linux. Should run on any operating system provided that a .NET compatible runtime is available. Translating this C# code into C++ or many other languages should be fairly easy. 5) Dependencies =============== Currently the code only needs a .NET Framework v2.0 compatible runtime and base class assemblies. It only references mscorlib.dll. More recent C# language features may be used to allow modern/short syntax, so a .NET v3+ compiler might be necessary. 6) Compilation ============== Visual Studio (2008) solution (.sln) and C# project (.csproj) files were generated by integrated development environment (IDE) MonoDevelop 2.4+. Microsoft VS2010 (and possibly other .NET IDEs) should be able to open these. This solution contains two projects in separate subfolders: 1) LibSSM2: actual LibSSM2 code 2) TestLibSSM2: NUnit tests in a separate DLL Here are methods to compile with command line tools, especially if you don't have an IDE installed. mono (Linux at least) --------------------- Tested on Linux x64. You need to have some mono/mono-core packages installed. a) Using xbuild (XBuild Engine, compatible to Microsoft MSBUILD) Usually xbuild is available by Linux package "mono-devel". Examples: (will create Debug configuration by default) xbuild xbuild /property:Configuration=Debug xbuild /property:Configuration=Release xbuild LibSSM2.sln xbuild LibSSM2/LibSSM2.csproj /property:Configuration=Release b) Using gmcs (Mono C# compiler) directly The manual page for "gmcs" says: "The Mono C# compiler by default only references three assemblies: mscorlib.dll, System.dll and System.Xml.dll." Now to compile the actual library from source files: .../LibSSM2> cd LibSSM2 .../LibSSM2/LibSSM2> gmcs -out:bin/Release/LibSSM2.dll -target:library *.cs If all went well the resulting library file should exist, roughly 14 KiB: bin/Release/LibSSM2.dll Most IDEs use bin/Debug and bin/Release subdirs for output. Advanced stuff: Mono Ahead-of-Time compilation (AOT), creating file LibSSM2.dll.so: mono --aot=full --optimize=all LibSSM2.dll Decompile AOT native code: objdump -d LibSSM2.dll.so > LibSSM2_aot.asm Use Intel syntax instead of default (AT&T): objdump -d LibSSM2.dll.so --disassembler-options=intel > LibSSM2_aot.masm Windows ------- C# compiler CSC.exe usually ships with modern Windows OS (Vista or later) as these versions already have a .NET Framework installed. There is a free Windows SDK downloadable from Microsoft, providing additional tools and documentation. Also free is the full integrated development environment (IDE) "Visual Studio, Express Edition". When you use additional stuff like SDK or VS, you can use "SDK Command Prompt" or "Visual Studio Command Prompt" etc. as these shortcuts provide paths to needed executables like csc.exe or msbuild.exe. If you don't want to install any tool I recommend creating a .BAT file where you can easily type the needed paths once. a) Using MSBUILD (Microsoft (R) Build Engine) With special command prompts, to compile the whole solution or just the main project: msbuild LibSSM2.sln msbuild LibSSM2\LibSSM2.csproj Sample content for a .BAT file using full paths: ----- REM with .NET framework 4 (full) installed: REM where msbuild REM e.g.: REM C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe REM C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe SET MSBUILDPATH="C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" REM solution or project file REM SET INPUT="LibSSM2\LibSSM2.csproj" SET INPUT="LibSSM2.sln" %MSBUILDPATH% %INPUT% ----- b) Using CSC (Microsoft (R) Visual C# 2010 Compiler) directly By default, optimizations are disabled. Specify /optimize+ to enable optimizations. csc.exe is sufficient Command Prompt" or similar csc /out:C:\LibSSM2.dll /target:library /optimize LibSSM2\*.cs Sample content for a .BAT file using full paths: ----- REM with .NET framework 4 (full) installed: REM where csc REM "C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\csc.exe" REM "C:\WINDOWS\Microsoft.NET\Framework\v3.5\csc.exe" REM Full path needed to allow being run from plain normal command prompt. REM Just csc.exe is sufficient when using SDK Command Prompt or similar. REM This would execute latest installed (e.g. v4) .NET C# compiler. SET CSCPATH="C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\csc.exe" SET INPUT="LibSSM2\*.cs" SET OUTPUT="LibSSM2\bin\Release\LibSSM2.dll" %CSCPATH% /out:%OUTPUT% /target:library /optimize %INPUT% ----- 7) Contribute ============= Any contributions, notes, hints, bug reports etc. are welcome. Code formatting: MonoDevelop style "Mono", Unix line endings, standard 8 char tabs. Some very long lines have been broken manually since MonoDevelop feature "Edit|Format|Format Document" won't do it. There is a simple Linux script "clean_whitespace.sh" useful to remove trailing whitespace before committing. 8) Implementation Notes ======================= Design goals ------------ Hopefully at least partially accomplished: 1) lean and efficient 2) reliable, especially for standard use cases 3) usable on limited Mono/.NET installations (i.e. Compact Framework devices like PocketPC) 4) easy to use, requiring only basic SSM2 protocol knowledge A perfect achievement of all these topics, e.g. highly efficient and very safe to use, may not be fully possible. These Subaru SSM2 packet classes are designed for object reusability which means these objects are immutable. Properties can be changed and will only affect corresponding packet bytes. I.e. once header info has been set, one can modify payload data, unchanged header bytes don't have to be rewritten. This implementation also avoids many backing fields as most properties directly rely on underlying packet buffer bytes. As an added benefit consistency problems between properties and actual packet bytes should not occur. Optimization ------------ Some C# compiler observations confirmed by tool "Reflector": Applies to both Mono (2.6.4) and Windows .NET (4) C# compilers, with optimizations turned on. These things don't really matter here as SSM2 uses a slow data rate but could be useful somewhere else. a) Simple calculation subtracting a field by two constants: int dataCount = this.count - HeaderLength - 1; --> int num = (base.count - 5) - 1; This is not optimal, uses two subtractions instead of one. Even Mono full AOT compilation (on x64 at least) does not optimize this inefficient IL away: 00000000000012b0 <Subaru_SSM2_Ssm2DataResponse_get_DataCount>: 12b0: 48 83 ec 08 sub rsp,0x8 12b4: 4c 89 3c 24 mov QWORD PTR [rsp],r15 12b8: 4c 8b ff mov r15,rdi 12bb: 49 63 47 18 movsxd rax,DWORD PTR [r15+0x18] 12bf: 83 e8 05 sub eax,0x5 12c2: 4c 8b f8 mov r15,rax 12c5: 41 ff cf dec r15d 12c8: 41 83 ff 01 cmp r15d,0x1 12cc: 7c 0e jl 12dc <Subaru_SSM2_Ssm2DataResponse_get_DataCount+0x2c> 12ce: 41 81 ff fe 00 00 00 cmp r15d,0xfe 12d5: 7f 05 jg 12dc <Subaru_SSM2_Ssm2DataResponse_get_DataCount+0x2c> 12d7: 49 8b c7 mov rax,r15 12da: eb 02 jmp 12de <Subaru_SSM2_Ssm2DataResponse_get_DataCount+0x2e> 12dc: 33 c0 xor eax,eax 12de: 4c 8b 3c 24 mov r15,QWORD PTR [rsp] 12e2: 48 83 c4 08 add rsp,0x8 12e6: c3 ret Solution: Grouping constants together yields expected smaller/better IL code - 1 subtraction only: int dataCount = this.count - (HeaderLength + 1); --> int num = base.count - 6; Native code of course gets slightly better as well: 00000000000012b0 <Subaru_SSM2_Ssm2DataResponse_get_DataCount>: 12b0: 48 83 ec 08 sub rsp,0x8 12b4: 4c 89 3c 24 mov QWORD PTR [rsp],r15 12b8: 4c 8b ff mov r15,rdi 12bb: 49 63 47 18 movsxd rax,DWORD PTR [r15+0x18] 12bf: 4c 8b f8 mov r15,rax 12c2: 41 83 ef 06 sub r15d,0x6 12c6: 41 83 ff 01 cmp r15d,0x1 12ca: 7c 0e jl 12da <Subaru_SSM2_Ssm2DataResponse_get_DataCount+0x2a> 12cc: 41 81 ff fe 00 00 00 cmp r15d,0xfe 12d3: 7f 05 jg 12da <Subaru_SSM2_Ssm2DataResponse_get_DataCount+0x2a> 12d5: 49 8b c7 mov rax,r15 12d8: eb 02 jmp 12dc <Subaru_SSM2_Ssm2DataResponse_get_DataCount+0x2c> 12da: 33 c0 xor eax,eax 12dc: 4c 8b 3c 24 mov r15,QWORD PTR [rsp] 12e0: 48 83 c4 08 add rsp,0x8 12e4: c3 ret b) Windows .NET CSC uses short versions of some IL instructions: Requiring 2 IL bytes: blt.s L_0015 while Mono compiler gmcs does not: Requiring 5 IL bytes: blt L_001b The behavior is exactly the same, the DLL will be slightly larger though. Multi-threading --------------- No special support is built in (no locks etc.) as this code has no knowledge where it will be used. Thread safety must be taken into account in the application at a higher level if needed. 9) Links ======== About Subaru ------------ http://en.wikipedia.org/wiki/Subaru http://www.subaru-global.com/ ecuExplorer ----------- "ecuExplorer is an open-source application that will connect to a Subaru ECU" C++, GPL2 license http://code.google.com/p/ecuexplorer/ .NET SSM -------- C# .NET, SSM2, GPL(?) license; library, tools and CarPC software http://ssm.codeplex.com/ FreeSSM ------- C++ Qt4, GPL3 license, SSM2 (SSM1 will be added soon?) http://freessm.berlios.de/