/LibSSM2

This C# library provides Subaru specific car diagnostic protocol messages. Reasonable new cars only, old cars use SSM1.

Primary LanguageC#GNU General Public License v3.0GPL-3.0

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/