├── .gitignore ├── COPYING.txt ├── LibSSM2.sln ├── LibSSM2 ├── AssemblyInfo.cs ├── ISsm2Packet.cs ├── LibSSM2.csproj ├── Ssm2DataResponse.cs ├── Ssm2Enums.cs ├── Ssm2InitRequest.cs ├── Ssm2InitResponse.cs ├── Ssm2Packet.cs ├── Ssm2ReadAddressesRequest.cs ├── Ssm2ReadAddressesResponse.cs ├── Ssm2ReadBlockRequest.cs ├── Ssm2ReadBlockResponse.cs ├── Ssm2WriteAddressRequest.cs └── Ssm2WriteAddressResponse.cs ├── README.txt ├── SSM2_Protocol.txt ├── TODO.txt ├── TestLibSSM2 ├── TestLibSSM2.csproj ├── TestSsm2InitRequest.cs ├── TestSsm2InitResponse.cs ├── TestSsm2Packet.cs ├── TestSsm2ReadAddressesRequest.cs ├── TestSsm2ReadAddressesResponse.cs ├── TestSsm2ReadBlockRequest.cs ├── TestSsm2ReadBlockResponse.cs ├── TestSsm2WriteAddressRequest.cs └── TestSsm2WriteAddressResponse.cs ├── clean_whitespace.sh └── gendarme.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # build dirs 2 | bin/ 3 | obj/ 4 | 5 | # Monodevelop binary files 6 | *.pidb 7 | 8 | # Monodevelop project userprefs (not important, last edit position, tabs etc.) 9 | *.userprefs 10 | 11 | # NUnit 12 | test-results/ 13 | TestResult.xml 14 | 15 | # Gendarme code analysis results 16 | *gendarme*.htm* 17 | -------------------------------------------------------------------------------- /COPYING.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /LibSSM2.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibSSM2", "LibSSM2\LibSSM2.csproj", "{60C26865-ACC4-450B-9030-3978314C7DDA}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestLibSSM2", "TestLibSSM2\TestLibSSM2.csproj", "{63A997C2-08F6-43F9-B089-5894D2833C28}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{50A06DA7-873C-49AF-8E19-5E1530D0BA34}" 9 | ProjectSection(SolutionItems) = preProject 10 | README.txt = README.txt 11 | SSM2_Protocol.txt = SSM2_Protocol.txt 12 | TODO.txt = TODO.txt 13 | EndProjectSection 14 | EndProject 15 | Global 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Debug|Any CPU = Debug|Any CPU 18 | Release|Any CPU = Release|Any CPU 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {60C26865-ACC4-450B-9030-3978314C7DDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {60C26865-ACC4-450B-9030-3978314C7DDA}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {60C26865-ACC4-450B-9030-3978314C7DDA}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {60C26865-ACC4-450B-9030-3978314C7DDA}.Release|Any CPU.Build.0 = Release|Any CPU 25 | {63A997C2-08F6-43F9-B089-5894D2833C28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {63A997C2-08F6-43F9-B089-5894D2833C28}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {63A997C2-08F6-43F9-B089-5894D2833C28}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {63A997C2-08F6-43F9-B089-5894D2833C28}.Release|Any CPU.Build.0 = Release|Any CPU 29 | EndGlobalSection 30 | GlobalSection(NestedProjects) = preSolution 31 | EndGlobalSection 32 | GlobalSection(MonoDevelopProperties) = preSolution 33 | StartupItem = TestLibSSM2\TestLibSSM2.csproj 34 | Policies = $0 35 | $0.TextStylePolicy = $1 36 | $1.inheritsSet = Mono 37 | $1.inheritsScope = text/plain 38 | $1.scope = text/x-csharp 39 | $0.CSharpFormattingPolicy = $2 40 | $2.inheritsSet = Mono 41 | $2.inheritsScope = text/x-csharp 42 | $2.scope = text/x-csharp 43 | $0.StandardHeader = $3 44 | $3.inheritsSet = GPLv3License 45 | description = Types for Subaru SSM2 car diagnostic protocol. 46 | version = 1.0 47 | EndGlobalSection 48 | EndGlobal 49 | -------------------------------------------------------------------------------- /LibSSM2/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // AssemblyInfo.cs: Assembly metadata. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System.Reflection; 23 | using System.Runtime.CompilerServices; 24 | 25 | // Information about this assembly is defined by the following attributes. 26 | // Change them to the values specific to your project. 27 | 28 | [assembly: AssemblyTitle("LibSSM2")] 29 | [assembly: AssemblyDescription("Types for SSM2 car diagnostic protocol.")] 30 | [assembly: AssemblyConfiguration("")] 31 | [assembly: AssemblyCompany("")] 32 | [assembly: AssemblyProduct("")] 33 | [assembly: AssemblyCopyright("2010 src0x")] 34 | [assembly: AssemblyTrademark("")] 35 | [assembly: AssemblyCulture("")] 36 | [assembly: System.CLSCompliant(true)] 37 | 38 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 39 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 40 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 41 | 42 | [assembly: AssemblyVersion("1.0.*")] 43 | 44 | // The following attributes are used to specify the signing key for the assembly, 45 | // if desired. See the Mono documentation for more information about signing. 46 | 47 | //[assembly: AssemblyDelaySign(false)] 48 | //[assembly: AssemblyKeyFile("")] 49 | -------------------------------------------------------------------------------- /LibSSM2/ISsm2Packet.cs: -------------------------------------------------------------------------------- 1 | // ISsm2Packet.cs: Interface that all SSM2 packet classes have to implement. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System; 23 | 24 | namespace Subaru.SSM2 25 | { 26 | 27 | /// 28 | /// Specifies common SSM2 packet features. 29 | /// 30 | public interface ISsm2Packet 31 | { 32 | Ssm2Device Destination { get; set; } 33 | Ssm2Device Source { get; set; } 34 | Ssm2Command Command { get; } 35 | 36 | /// 37 | /// Currently used packet size. 38 | /// May be less than capacity. 39 | /// Valid for valid packet content only. 40 | /// (For debugging purposes mostly.) 41 | /// 42 | int Size { get; } 43 | 44 | /// 45 | /// Report currently allocated buffer size. 46 | /// (For debugging purposes mostly.) 47 | /// 48 | /// 49 | /// Should be ≥ minimum (6). 50 | /// 51 | int Capacity { get; } 52 | 53 | /// 54 | /// Validates packet including checksum. 55 | /// Checks both common and packet type specific characteristics. 56 | /// 57 | /// true if everything is OK. 58 | bool Check (); 59 | 60 | // Can be useful in debugger, therefore implemented as property getter. 61 | /// 62 | /// All bytes till before checksum (incl. header) are used for checksum. 63 | /// Assumes Count is total packet length including checksum byte. 64 | /// (For debugging purposes mostly.) 65 | /// 66 | byte ChecksumCalculated { get; } 67 | 68 | /// 69 | /// Calculate and compare checksum. 70 | /// 71 | /// true if checksum is ok 72 | bool IsChecksumOk { get; } 73 | 74 | void FromBytes (byte[] bytes); 75 | 76 | /// 77 | /// Finish the packet. 78 | /// (Checksum and inline length byte.) 79 | /// 80 | void Finish (); 81 | 82 | byte[] ToBytesCopy (); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /LibSSM2/LibSSM2.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {60C26865-ACC4-450B-9030-3978314C7DDA} 9 | Library 10 | Subaru.SSM2 11 | LibSSM2 12 | v3.5 13 | Contains types for Subaru SSM2 procotol. 14 | 1.0 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug 21 | DEBUG 22 | prompt 23 | 4 24 | false 25 | 26 | 27 | none 28 | true 29 | bin\Release 30 | prompt 31 | 4 32 | false 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /LibSSM2/Ssm2DataResponse.cs: -------------------------------------------------------------------------------- 1 | // Ssm2DataResponse.cs: Abstract class providing common functionality 2 | // for data reponse packet types. 3 | 4 | /* Copyright (C) 2010 src0x 5 | * 6 | * This file is part of LibSSM2. 7 | * 8 | * LibSSM2 is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * LibSSM2 is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with LibSSM2. If not, see . 20 | */ 21 | 22 | 23 | using System; 24 | using System.Collections.Generic; 25 | using System.Diagnostics; 26 | 27 | namespace Subaru.SSM2 28 | { 29 | // TODO Find attribute to hide this abstract class (code completion). 30 | // only valid on properties etc. 31 | // [DebuggerBrowsable(DebuggerBrowsableState.Never)] 32 | 33 | /// 34 | /// Abstract base class to provide the very similar functionality 35 | /// for variable data reponse packet types. 36 | /// Should not be used by consumer code. 37 | /// Used by read-addresses-A8 and read-block-A0 response packets 38 | /// as these packets differ only by command byte. 39 | /// Packet consists of: 5 header + X data + 1 checksum bytes. 40 | /// 41 | [DebuggerNonUserCode] 42 | public abstract class Ssm2DataResponse : Ssm2Packet 43 | { 44 | // do require at least one content byte, min is 7 bytes 45 | private const int PacketSizeSpecificMin = HeaderLength + 1 + 1; 46 | 47 | #region constructors 48 | 49 | protected Ssm2DataResponse () 50 | { 51 | this.count = PacketSizeSpecificMin; 52 | } 53 | 54 | protected Ssm2DataResponse (byte[] buffer) 55 | : base (buffer, PacketSizeSpecificMin) 56 | { 57 | } 58 | 59 | /// 60 | /// Create a new packet. 61 | /// Uses optimal buffer size. Packet is not finished yet! 62 | /// 63 | protected Ssm2DataResponse (Ssm2Device destination, 64 | Ssm2Device source, 65 | IList data) 66 | : base (HeaderLength + 1 + data.Count) 67 | { 68 | // needed buffer size: 5 byte header + x * data + 1 checksum 69 | 70 | this.Destination = destination; 71 | this.Source = source; 72 | this.Data = data; 73 | // Data setter has already set Count. 74 | } 75 | 76 | #endregion constructors 77 | 78 | // Implementation notes: 79 | // Returning IList instead of IEnumerable because of performance benefits 80 | // for following analysis (e.g. LINQ queries). 81 | 82 | /// 83 | /// Gets or sets the data. 84 | /// 85 | /// 86 | /// The data. 87 | /// 88 | public IList Data { 89 | get { 90 | int adrCount = DataCount; 91 | var data = new List (adrCount); 92 | // optimize using local variable 93 | byte[] buffer = this.buffer; 94 | // set index to 1st addresses byte = HeaderLength, there is no padding byte 95 | int i = HeaderLength; 96 | for (int adrNr = 0; adrNr < adrCount; adrNr++) { 97 | data.Add (buffer[i++]); 98 | } 99 | return data; 100 | } 101 | set { 102 | // optimize using local variable 103 | int i = HeaderLength; 104 | // foreach well optimized by compiler when using an array 105 | foreach (int d in value) { 106 | buffer[i++] = (byte)d; 107 | } 108 | UpdateFlags (SetProperties.DataAll); 109 | 110 | // total packet size known here, include checksum 111 | this.count = i + 1; 112 | } 113 | } 114 | 115 | /// 116 | /// Calculates the number of addresses based on packet length. 117 | /// 118 | /// 0 if there is an error. 119 | public int DataCount { 120 | get { 121 | // packet should consist of: 5 byte header + x * data bytes + 1 checksum 122 | int dataCount = this.count - (HeaderLength + 1); 123 | // grouping constants together optimizes IL code: 124 | //int dataCount = this.count - (HeaderLength + 1); 125 | if (dataCount >= 1 && dataCount <= (PacketSizeMax - HeaderLength - 1)) 126 | return dataCount; 127 | else 128 | return 0; 129 | } 130 | } 131 | 132 | public override bool Check () 133 | { 134 | return this.count >= PacketSizeSpecificMin 135 | && base.Check (); 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /LibSSM2/Ssm2Enums.cs: -------------------------------------------------------------------------------- 1 | // Ssm2Enums.cs: Public enums to be used for SSM2 types. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | namespace Subaru.SSM2 23 | { 24 | 25 | /// 26 | /// SSM2 command identifier. 27 | /// (Last two hex characters represent actual packet byte, useful for debugging.) 28 | /// 29 | public enum Ssm2Command : byte 30 | { 31 | None = 0, 32 | ReadBlockRequestA0 = 0xa0, 33 | ReadBlockResponseE0 = 0xe0, 34 | ReadAddressesRequestA8 = 0xa8, 35 | ReadAddressesResponseE8 = 0xe8, 36 | WriteBlockRequestB0 = 0xb0, 37 | WriteBlockResponseF0 = 0xf0, 38 | WriteAddressRequestB8 = 0xb8, 39 | WriteAddressResponseF8 = 0xf8, 40 | InitRequestBF = 0xbf, 41 | InitResponseFF = 0xff 42 | } 43 | 44 | /// 45 | /// SSM2 device ID. 46 | /// (Last two hex characters represent actual packet byte, useful for debugging.) 47 | /// Many different IDs for various control units may be valid, 48 | /// depending on the model. 49 | /// You can always provide own/undefined values by casting 50 | /// like this: (Ssm2Device)0x123. 51 | /// 52 | public enum Ssm2Device : byte 53 | { 54 | None = 0, 55 | Engine10 = 0x10, 56 | Transmission18 = 0x18, 57 | DiagnosticToolF0 = 0xf0 58 | } 59 | 60 | /// 61 | /// Well-known constant buffer indices in any SSM2 packet. 62 | /// (Mostly for internal and testing purposes.) 63 | /// 64 | public enum Ssm2PacketIndex 65 | { 66 | /// 67 | /// This first byte is always supposed to be 128 = 0x80. 68 | /// 69 | Header, 70 | /// 71 | /// Destination device. 72 | /// Typically 0x10 = engine, 0x18 = transmission, 0xF0 = diagnostic tool. 73 | /// 74 | Destination, 75 | /// 76 | /// Source device. Same principle as Destination. 77 | /// 78 | Source, 79 | /// 80 | /// Inline payload length, counting all following bytes except checksum. 81 | /// 82 | DataSize, 83 | Command, 84 | /// 85 | /// Generic data, length varies. 86 | /// Some packet types use a padding byte as first data byte. 87 | /// 88 | Data 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /LibSSM2/Ssm2InitRequest.cs: -------------------------------------------------------------------------------- 1 | // Ssm2InitRequest.cs: SSM2 packet class for init request. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | 25 | namespace Subaru.SSM2 26 | { 27 | 28 | /// 29 | /// Init request packet. Does not have specific properties. 30 | /// This packet type is usually created by the tester and sent to the car control unit. 31 | /// (Packet always consists of 6 bytes: 5 byte header + 1 checksum. 32 | /// Typically for engine it is {0x80, 0x10, 0xF0, 0x01, 0xBF, 0x40} ) 33 | /// 34 | public sealed class Ssm2InitRequest : Ssm2Packet 35 | { 36 | private const int PacketSizeSpecificFixed = HeaderLength + 1; 37 | 38 | #region constructors 39 | 40 | public Ssm2InitRequest () : base (PacketSizeSpecificFixed) 41 | { 42 | // base class constructor will be called anyway 43 | // : base() 44 | // this type of packet has fixed length 45 | this.count = PacketSizeSpecificFixed; 46 | this.propsSet = SetProperties.AllButChecksum; 47 | } 48 | 49 | public Ssm2InitRequest (byte[] buffer) : base (buffer, PacketSizeSpecificFixed) 50 | { 51 | this.propsSet = SetProperties.AllButChecksum; 52 | } 53 | 54 | /// 55 | /// Creates a complete init request packet. 56 | /// (Uses optimal buffer size of 6 bytes.) 57 | /// 58 | /// 59 | /// A 60 | /// 61 | /// 62 | /// A 63 | /// 64 | public Ssm2InitRequest (Ssm2Device destination, 65 | Ssm2Device source) 66 | : this () 67 | { 68 | this.Destination = destination; 69 | this.Source = source; 70 | 71 | this.Finish (); 72 | } 73 | 74 | #endregion constructors 75 | 76 | public override bool Check () 77 | { 78 | return this.Command == Ssm2Command.InitRequestBF 79 | && this.count == PacketSizeSpecificFixed 80 | && base.Check (); 81 | } 82 | 83 | protected override void SetConstBytes () 84 | { 85 | base.Command = Ssm2Command.InitRequestBF; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /LibSSM2/Ssm2InitResponse.cs: -------------------------------------------------------------------------------- 1 | // Ssm2InitResponse.cs: SSM2 packet class for init response. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | 25 | namespace Subaru.SSM2 26 | { 27 | 28 | /// 29 | /// Init response packet. 30 | /// This packet type is usually created by control unit and sent to the tester. 31 | /// Packet consists of: 5 byte header + 3 SSMID + 5 ROMID + X capability bytes + 1 checksum. 32 | /// Capability bytes length is not constant, usually 32, 48 or 96 bytes seen so far. 33 | /// 34 | public sealed class Ssm2InitResponse : Ssm2Packet 35 | { 36 | const int LengthSsmID = 3; 37 | const int LengthRomID = 5; 38 | // TODO Research actual capability bytes minimum of oldest SSM2 cars. 39 | // Probably 16 or 32, rather not 0. 40 | const int CapabilitiesMin = 0; 41 | const int CapabilitiesMax = PacketSizeMax - PacketSizeSpecificMin; 42 | 43 | const int PacketSizeSpecificMin = HeaderLength + LengthSsmID + LengthRomID + CapabilitiesMin + 1; 44 | 45 | const int IndexSsmID = HeaderLength; 46 | const int IndexRomID = IndexSsmID + LengthSsmID; 47 | const int IndexCapabilities = IndexRomID + LengthRomID; 48 | 49 | #region constructors 50 | 51 | public Ssm2InitResponse () 52 | { 53 | this.count = PacketSizeSpecificMin; 54 | } 55 | 56 | public Ssm2InitResponse (byte[] buffer) : base (buffer, PacketSizeSpecificMin) 57 | { 58 | } 59 | 60 | // TODO argument checking 61 | /// 62 | /// Creates a complete InitResponse packet. 63 | /// 64 | public Ssm2InitResponse (Ssm2Device destination, 65 | Ssm2Device source, 66 | byte[] ssmID, 67 | byte[] romID, 68 | byte[] capabilities) 69 | : base (capabilities.Length + (HeaderLength + LengthSsmID + LengthRomID + 1)) 70 | { 71 | this.Destination = destination; 72 | this.Source = source; 73 | 74 | SetSsmID (ssmID); 75 | SetRomID (romID); 76 | // setting capability bytes also updates size 77 | SetCapabilities (capabilities); 78 | 79 | this.Finish (); 80 | } 81 | 82 | 83 | #endregion constructors 84 | 85 | #region data access 86 | 87 | // Implementation notes: 88 | // Since array implements IList, returning an array seems 89 | // to be both versatile and efficient. 90 | // But properties (normally) should not return an array, 91 | // therefore using plain methods instead. 92 | 93 | /// 94 | /// Return a copy of the 3 SSMID bytes. 95 | /// 96 | /// 97 | /// A 98 | /// 99 | public byte[] GetSsmID () 100 | { 101 | return CopyPart (IndexSsmID, LengthSsmID); 102 | } 103 | 104 | /// 105 | /// Sets SSMID 106 | /// 107 | /// 108 | /// Always 3 bytes e.g. "{0xA2, 0x10, 0x12}". 109 | /// 110 | /// 111 | /// Array length must be 3. 112 | public void SetSsmID (byte[] ssmID) 113 | { 114 | TakePart (ssmID, IndexSsmID, LengthSsmID); 115 | UpdateFlags (SetProperties.Data1); 116 | } 117 | 118 | /// 119 | /// Returns a copy of the 5 ROMID bytes. 120 | /// 121 | /// 122 | /// A 123 | /// 124 | public byte[] GetRomID () 125 | { 126 | return CopyPart (IndexRomID, LengthRomID); 127 | } 128 | 129 | /// 130 | /// Sets ROMID. 131 | /// 132 | /// 133 | /// Always 5 bytes e.g. "{0x1B, 0x14, 0x40, 0x05, 0x05}". 134 | /// 135 | /// 136 | /// Array length must be 5. 137 | public void SetRomID (byte[] romID) 138 | { 139 | TakePart (romID, IndexRomID, LengthRomID); 140 | UpdateFlags (SetProperties.Data2); 141 | } 142 | 143 | /// 144 | /// Get the number of capability bytes. 145 | /// (Calculated via packet size. 146 | /// Usually 32, 48 or 96 bytes seen so far.) 147 | /// 148 | public int CapabilitiesLength { 149 | get { 150 | // capability bytes are the only variable content 151 | int length = this.count - PacketSizeSpecificMin; 152 | return (length > 0 && length <= CapabilitiesMax) ? length : 0; 153 | } 154 | } 155 | 156 | /// 157 | /// Returns a copy of the capability bytes. 158 | /// (Lengths of 32 = 0x20, 48 = 0x30 or 96 = 0x60 bytes seen so far.) 159 | /// 160 | /// 161 | /// A 162 | /// 163 | public byte[] GetCapabilities () 164 | { 165 | return CopyPart (IndexCapabilities, CapabilitiesLength); 166 | } 167 | 168 | /// 169 | /// Set capability bytes. 170 | /// 171 | /// 172 | /// Capabilities. 173 | /// 174 | /// 175 | /// 176 | /// Length out of range. Must be greater than 1. 177 | /// 178 | public void SetCapabilities (byte[] capabilities) 179 | { 180 | if (capabilities == null) 181 | throw new ArgumentNullException (); 182 | int length = capabilities.Length; 183 | if (length < CapabilitiesMin || length > CapabilitiesMax) 184 | throw new ArgumentOutOfRangeException ("capabilities.Length", 185 | length, 186 | CapabilitiesMin.ToString() + " ≤ x ≤ " + CapabilitiesMax.ToString()); 187 | Array.Copy (capabilities, 0, this.buffer, IndexCapabilities, length); 188 | UpdateFlags (SetProperties.Data3); 189 | 190 | // size known here 191 | this.count = PacketSizeSpecificMin + length; 192 | } 193 | 194 | #endregion data access 195 | 196 | public override bool Check () 197 | { 198 | return this.Command == Ssm2Command.InitResponseFF 199 | && this.count >= PacketSizeSpecificMin 200 | && base.Check (); 201 | } 202 | 203 | protected override void SetConstBytes () 204 | { 205 | base.Command = Ssm2Command.InitResponseFF; 206 | // no padding byte 207 | } 208 | 209 | private byte[] CopyPart (int index, int length) 210 | { 211 | byte[] bytes = new byte[length]; 212 | Array.Copy (this.buffer, index, bytes, 0, length); 213 | return bytes; 214 | } 215 | 216 | private void TakePart (byte[] bytes, int index, int length) 217 | { 218 | if (bytes == null) 219 | throw new ArgumentNullException (); 220 | if (bytes.Length != length) 221 | throw new ArgumentOutOfRangeException ( 222 | ".Length", bytes.Length, "must be " + length.ToString()); 223 | Array.Copy (bytes, 0, this.buffer, index, length); 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /LibSSM2/Ssm2Packet.cs: -------------------------------------------------------------------------------- 1 | // Ssm2Packet.cs: SSM2 packet base class. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System; 23 | using System.Diagnostics; 24 | 25 | namespace Subaru.SSM2 26 | { 27 | // Not working in MonoDevelop ? 28 | //[DebuggerDisplay("Size={Size}|Check()={Check()}")] 29 | //[DebuggerDisplay("Size={count}")] 30 | 31 | /// 32 | /// Subaru SSM2 packet base class. 33 | /// Designed for object reusability which means immutable. 34 | /// Properties can be changed and will only affect those packet bytes. 35 | /// I.e. once header info has been set, one can modify payload data, header bytes won't be rewritten. 36 | /// Also avoids many backing fields since most properties directly read/write packet bytes. 37 | /// 38 | public class Ssm2Packet : ISsm2Packet 39 | { 40 | // Implementation notes: This class has no abstract members 41 | // in order to allow this class to be used as concrete base class. 42 | // May want to get common info out of any packet object. 43 | 44 | /// 45 | /// To record which properties have already been set. 46 | /// Will be checked by the Finish() method. 47 | /// 48 | [Flags] 49 | protected enum SetProperties 50 | { 51 | Source = 1, 52 | Destination = 2, 53 | /// 54 | /// DataX for specific packet types. All Data bits must be set. 55 | /// If a packet has less than 3 data properties, combine DataX accordingly as DataAll will be checked. 56 | /// 57 | Data1 = 16, 58 | Data2 = 32, 59 | Data3 = 64, 60 | DataAll = Data1 | Data2 | Data3, 61 | Checksum = 128, 62 | AllButChecksum = Source | Destination | DataAll, 63 | AllOk = Source | Destination | DataAll | Checksum 64 | } 65 | 66 | 67 | /// 68 | /// Returns a specific Ssm2Packet type based on given content. 69 | /// Does not validate the packet, so manually call the Check method afterwards! 70 | /// 71 | /// 72 | /// A containing the packet. 73 | /// The packet must start at index 0 though the array may be larger than needed. 74 | /// 75 | /// 76 | /// A subclass or null if the packet type could not be recognized. 77 | /// 78 | /// 79 | /// 80 | public static Ssm2Packet NewFromBytes (byte[] bytes) 81 | { 82 | if (bytes == null) 83 | throw new ArgumentNullException (); 84 | // check generic minimum size in order to get command byte 85 | if (bytes.Length < PacketSizeMin) 86 | throw new ArgumentOutOfRangeException ("bytes.Length < Minimum (6)"); 87 | 88 | Ssm2Packet p; 89 | // Read type directly from command byte (5th byte). 90 | // Each derived class constructor checks its requirements. 91 | switch ((Ssm2Command)bytes[(int)Ssm2PacketIndex.Command]) { 92 | case Ssm2Command.ReadAddressesRequestA8: 93 | p = new Ssm2ReadAddressesRequest (bytes); 94 | break; 95 | case Ssm2Command.ReadAddressesResponseE8: 96 | p = new Ssm2ReadAddressesResponse (bytes); 97 | break; 98 | case Ssm2Command.WriteAddressRequestB8: 99 | p = new Ssm2WriteAddressRequest (bytes); 100 | break; 101 | case Ssm2Command.WriteAddressResponseF8: 102 | p = new Ssm2WriteAddressResponse (bytes); 103 | break; 104 | case Ssm2Command.InitRequestBF: 105 | p = new Ssm2InitRequest (bytes); 106 | break; 107 | case Ssm2Command.InitResponseFF: 108 | p = new Ssm2InitResponse (bytes); 109 | break; 110 | case Ssm2Command.ReadBlockRequestA0: 111 | p = new Ssm2ReadBlockRequest (bytes); 112 | break; 113 | case Ssm2Command.ReadBlockResponseE0: 114 | p = new Ssm2ReadBlockResponse (bytes); 115 | break; 116 | default: 117 | return null; 118 | } 119 | p.FromBytes (bytes); 120 | return p; 121 | } 122 | 123 | 124 | 125 | /// 126 | /// Thoretical SSM2 packet size limit (because of maximum length byte) is 127 | /// 260 bytes: 4 header bytes incl. data size byte + 255 bytes content + checksum. 128 | /// (Tests on modern cars indicate actual limit of 255!) 129 | /// 130 | public const int PacketSizeMax = 4 + 255 + 1; 131 | // A packet has at least 6 bytes (5 Header bytes + 1 checksum byte) 132 | public const int PacketSizeMin = HeaderLength + 1; 133 | 134 | /// 135 | /// All SSM2 packets start with this byte (128 = 0x80) 136 | /// 137 | private const byte FirstByte = 0x80; 138 | 139 | /// 140 | /// Number of SSM2 header pytes is 5, 141 | /// = minimum packet size excluding checksum. 142 | /// 143 | protected const int HeaderLength = 5; 144 | 145 | #region fields 146 | 147 | // Implementation note: 148 | // Not using List as storage 149 | // because cannot reuse an existing buffer as 150 | // there is no List-constructor taking an existing array. 151 | // Therefore using a byte[] array plus a count field instead. 152 | 153 | /// 154 | /// Storage to use, make sure it is big enough. 155 | /// Use constant MaxBytesPacket. 156 | /// 157 | protected byte[] buffer; 158 | 159 | // hide in debugger since shown via property anyway 160 | /// 161 | /// Currently used packet size. 162 | /// Can be smaller than buffer size in order to (re)use a bigger buffer. 163 | /// 164 | [DebuggerBrowsable(DebuggerBrowsableState.Never)] 165 | protected int count; 166 | 167 | protected SetProperties propsSet; 168 | 169 | #endregion fields 170 | 171 | #region constructors 172 | 173 | /// 174 | /// Creates a SSM2 packet. 175 | /// Afterwards you have to set all properties and 176 | /// call Finish() to complete the packet. 177 | /// (This constructor allocates maximum possible packet size of 260 bytes.) 178 | /// 179 | public Ssm2Packet () : this (PacketSizeMax) 180 | { 181 | // set default size 182 | this.count = PacketSizeMin; 183 | SetFirstByte (); 184 | // If used from derived classes then 185 | // this is calling the overriden method!!! 186 | this.SetConstBytes (); 187 | } 188 | 189 | /// 190 | /// Takes given (empty) storage buffer and sets first byte. 191 | /// Afterwards you have to set all properties and 192 | /// call Construct() to finish the packet. 193 | /// This constructor is not meant for parsing an existing packet, 194 | /// use static method NewFromBytes instead or 195 | /// instance method FromBytes instead! 196 | /// 197 | /// 198 | /// A . Minimum 199 | /// 200 | /// 201 | /// If buffer.Length < minimum (6). 202 | /// 203 | public Ssm2Packet (byte[] buffer) : this (buffer, PacketSizeMin) 204 | { 205 | } 206 | 207 | /// 208 | /// Assures minimum capacity of given buffer. 209 | /// Useful when specific minimum or fixed packet size is known. 210 | /// Also sets packet size to given capacity. 211 | /// 212 | protected Ssm2Packet (byte[] buffer, int capacityMin) 213 | { 214 | TakeBuffer (buffer, capacityMin); 215 | this.count = capacityMin; 216 | SetFirstByte (); 217 | this.SetConstBytes (); 218 | } 219 | 220 | /// 221 | /// Creates a new packet with specified capacity. 222 | /// Afterwards you have to set all properties and 223 | /// call Construct() to finish the packet. 224 | /// 225 | /// 226 | /// Maximum packet size. 227 | /// 228 | /// 229 | /// Capacity ≥ 6 required. 230 | /// 231 | public Ssm2Packet (int capacity) 232 | { 233 | if (capacity < PacketSizeMin) 234 | throw new ArgumentOutOfRangeException ("buffer.Length", 235 | capacity, "< minimum of " + PacketSizeMin.ToString()); 236 | 237 | this.buffer = new byte[capacity]; 238 | this.count = PacketSizeMin; 239 | SetFirstByte (); 240 | this.SetConstBytes (); 241 | } 242 | 243 | #endregion constructors 244 | 245 | 246 | /// 247 | /// Parses packet by taking packet bytes, does not use a copy! 248 | /// Assumes complete packet, does not validate. 249 | /// May want to call Check () afterwards. 250 | /// (Packet size is being calculated based on packet length byte.) 251 | /// 252 | /// 253 | /// A . Length can be larger than needed. 254 | /// 255 | /// 256 | /// 257 | /// 258 | /// Length ≥ 6 required. 259 | /// 260 | public virtual void FromBytes (byte[] buffer) 261 | { 262 | TakeBuffer (buffer, PacketSizeMin); 263 | // Calculate packet size based on DataSize byte so given byte[] can be larger than needed. 264 | // total count = DataSize + remaining header bytes + checksum byte 265 | this.count = this.PayloadSize + ((int)Ssm2PacketIndex.DataSize + 1 + 1); 266 | if (buffer.Length < this.count) 267 | throw new ArgumentOutOfRangeException ("buffer.Length < expected"); 268 | // Assume packet to be complete incl. checksum. 269 | this.propsSet = SetProperties.AllOk; 270 | } 271 | 272 | /// 273 | /// Returns a copy of the actual packet bytes. 274 | /// May return empty array or less bytes if packet is incomplete. 275 | /// Guaranteed to not return null. 276 | /// Use method Check () before to assure validity. 277 | /// 278 | /// 279 | /// A . 280 | /// 281 | public byte[] ToBytesCopy () 282 | { 283 | int count = this.count; 284 | byte[] copy = new byte[count]; 285 | Array.Copy (this.buffer, copy, count); 286 | return copy; 287 | } 288 | 289 | /// 290 | /// Command. 291 | /// (For debugging mostly, = 5th packet byte.) 292 | /// 293 | public Ssm2Command Command { 294 | get { return (Ssm2Command)buffer[(int)Ssm2PacketIndex.Command]; } 295 | protected set { 296 | this.buffer[(int)Ssm2PacketIndex.Command] = (byte)value; 297 | } 298 | } 299 | 300 | public Ssm2Device Source { 301 | get { return (Ssm2Device)buffer[(int)Ssm2PacketIndex.Source]; } 302 | set { 303 | if (value == this.Source) 304 | return; 305 | this.buffer[(int)Ssm2PacketIndex.Source] = (byte)value; 306 | UpdateFlags (SetProperties.Source); 307 | } 308 | } 309 | 310 | public Ssm2Device Destination { 311 | get { return (Ssm2Device)buffer[(int)Ssm2PacketIndex.Destination]; } 312 | set { 313 | if (value == this.Destination) 314 | return; 315 | this.buffer[(int)Ssm2PacketIndex.Destination] = (byte)value; 316 | UpdateFlags (SetProperties.Destination); 317 | } 318 | } 319 | 320 | /// 321 | /// Currently used packet size. 322 | /// May be less than capacity. 323 | /// For debugging purposes mostly. 324 | /// Valid for valid packet only. 325 | /// 326 | public int Size { 327 | get { return this.count; } 328 | } 329 | 330 | /// 331 | /// Report currently allocated buffer size. 332 | /// (For debugging purposes mostly.) 333 | /// 334 | /// 335 | /// Should be ≥ minimum (6) for all packet types. 336 | /// 337 | public int Capacity { 338 | // constructors and methods should assure buffer != null 339 | get { return this.buffer.Length; } 340 | // get { return this.buffer != null ? this.buffer.Length : 0; } 341 | } 342 | 343 | /// 344 | /// Calculate and compare checksum. 345 | /// 346 | /// true if checksum is ok 347 | public bool IsChecksumOk { 348 | // last byte is always checksum 349 | get { return (this.buffer[this.count - 1] == this.ChecksumCalculated); } 350 | } 351 | 352 | // Can be useful in debugger, therefore implemented as property getter. 353 | /// 354 | /// All bytes till before checksum (incl. header) are used for checksum. 355 | /// Assumes Count is total packet length including checksum byte. 356 | /// (For debugging purposes mostly.) 357 | /// 358 | public byte ChecksumCalculated { 359 | get { 360 | // Checksum is lowest byte of sum 361 | // beginning with first packet byte, 362 | // excluding last byte (checksum itself). 363 | byte[] b = this.buffer; 364 | int s = 0; 365 | int m = this.count - 1; 366 | for (int i = 0; i < m; i++) 367 | s += b[i]; 368 | 369 | // not necessary: (byte)(s & 0xFF) 370 | return (byte)s; 371 | } 372 | } 373 | 374 | // To be overriden in order to include checking of type specific features. 375 | /// 376 | /// Validate packet completely including checksum. 377 | /// Checks common and packet type specific characteristics. 378 | /// 379 | /// true if everything is OK. 380 | public virtual bool Check () 381 | { 382 | int c = this.count; 383 | return (propsSet == SetProperties.AllOk 384 | && buffer[(int)Ssm2PacketIndex.Header] == FirstByte 385 | && c >= PacketSizeMin 386 | && PayloadSize == c - HeaderLength 387 | && Destination != Source 388 | && IsChecksumOk); 389 | } 390 | 391 | 392 | /// 393 | /// Finish the packet. 394 | /// (Checksum and inline length byte.) 395 | /// Also checks if all properties have been set. 396 | /// 397 | /// 398 | /// Not all required properties have been set. 399 | public void Finish () 400 | { 401 | // if all set or nothing has changed then there is nothing to do 402 | if (propsSet == SetProperties.AllOk) 403 | return; 404 | 405 | if (propsSet != SetProperties.AllButChecksum) { 406 | SetProperties missing = (SetProperties)(SetProperties.AllButChecksum - this.propsSet); 407 | throw new InvalidOperationException ("Properties not set: " + missing.ToString ()); 408 | } 409 | 410 | // Assumes full packet size incl. checksum! 411 | // optimize using local copy 412 | int count = this.count; 413 | 414 | // set data size byte (4th byte), = total packet size - 5 415 | // counting bytes from command (5th) byte till end, excluding last byte = checksum 416 | buffer[(int)Ssm2PacketIndex.DataSize] = 417 | (byte)(count - ((int)Ssm2PacketIndex.DataSize + 2)); 418 | 419 | // reserve last byte for checksum, checksum method assumes Count of full packet 420 | buffer[count - 1] = ChecksumCalculated; 421 | this.propsSet = SetProperties.AllOk; 422 | } 423 | 424 | // overriding Equals, GetHashCode etc. not necessary 425 | // but provide much better performance if used 426 | 427 | public override bool Equals(object obj) 428 | { 429 | if (obj == null) 430 | return false; 431 | 432 | Ssm2Packet p = obj as Ssm2Packet; 433 | if (p == null) 434 | return false; 435 | 436 | // Return true if the data matches: 437 | return (this.GetHashCode () == p.GetHashCode ()); 438 | } 439 | 440 | public bool Equals(Ssm2Packet p) 441 | { 442 | if (p == null) 443 | return false; 444 | return (this.GetHashCode () == p.GetHashCode ()); 445 | } 446 | 447 | public override int GetHashCode() 448 | { 449 | // Tested: buffer.GetHashCode () does 450 | // not produce hash based on content! 451 | // Arrays with same size and content yield different hash! 452 | 453 | // The single SSM2 checksum byte is not sufficient 454 | // as many different packets can have same checksum. 455 | // XOR 456 | return this.count ^ this.ChecksumCalculated; 457 | } 458 | 459 | 460 | #region private/protected 461 | 462 | /// 463 | /// Get payload length byte (4th header byte). 464 | /// Payload consists of command byte (5th) to last-1 (excluding checksum) byte. 465 | /// Therefore payload is total packet length minus 5 (4 + 1). 466 | /// 467 | protected byte PayloadSize { 468 | get { return this.buffer[(int)Ssm2PacketIndex.DataSize]; } 469 | } 470 | 471 | // Private access is sufficient since derived class 472 | // constructors should call a base class constructor. 473 | private void SetFirstByte () 474 | { 475 | // 1st packet byte is always 128 = 0x80 476 | this.buffer[(int)Ssm2PacketIndex.Header] = FirstByte; 477 | } 478 | 479 | /// 480 | /// Sets the const bytes except first packet byte. 481 | /// (Must be overriden by derived classes 482 | /// to set command and possible padding bytes.) 483 | /// 484 | protected virtual void SetConstBytes () 485 | { 486 | } 487 | 488 | /// 489 | /// Set flag to indicate that this part of the packet has been set. 490 | /// Also unsets checksum flag as it needs recalculation in method Finish(). 491 | /// 492 | /// 493 | /// The flag to set. 494 | /// 495 | protected void UpdateFlags (SetProperties toSet) 496 | { 497 | SetProperties props = this.propsSet; 498 | // set flag 499 | props |= toSet; 500 | 501 | // unset checksum flag 502 | // "~": bitwise complement operation on its operand, 503 | // which has the effect of reversing each bit 504 | props &= ~SetProperties.Checksum; 505 | 506 | this.propsSet = props; 507 | } 508 | 509 | /// 510 | /// Takes the buffer and checks for minimum length. 511 | /// 512 | /// 513 | /// Buffer. 514 | /// 515 | /// 516 | /// Minimum buffer length. 517 | /// 518 | /// 519 | /// Is thrown when an argument passed to a method is invalid because it is . 520 | /// 521 | /// 522 | /// If buffer.Length < minimum. 523 | /// 524 | protected void TakeBuffer (byte[] buffer, int minLength) 525 | { 526 | if (buffer == null) 527 | throw new ArgumentNullException ("buffer"); 528 | if (buffer.Length < minLength) 529 | throw new ArgumentOutOfRangeException ("buffer.Length", 530 | buffer.Length, "must be ≥ " + minLength.ToString ()); 531 | this.buffer = buffer; 532 | // set size to min length for now 533 | this.count = minLength; 534 | } 535 | 536 | // TODO Could be stripped in Release version 537 | //[System.Diagnostics.Conditional("DEBUG")] 538 | // Might just use 24 bits without complaining. 539 | // Currently used by Ssm2WriteAddressRequest and Ssm2ReadBlockRequest 540 | /// 541 | /// Throw ArgumentOutOfRangeException if outside valid range: 0 ≤ address ≤ 0xFFFFFF. 542 | /// (SSM2 addresses consist of 3 bytes allowing 16 MiB address space.) 543 | /// 544 | /// 545 | /// A 546 | /// 547 | /// 548 | static protected void AssertAddress (int address) 549 | { 550 | if (address < 0 || address > 0xffffff) 551 | throw new ArgumentOutOfRangeException ("address", 552 | address, "0 ≤ address ≤ 0xFFFFFF"); 553 | } 554 | 555 | // common functionality for some derived types 556 | protected int GetAddress (int index) 557 | { 558 | // optimize using local variable 559 | byte[] buffer = this.buffer; 560 | // big endian = most significant byte first 561 | // 3 bytes per address = 24 bits address space 562 | return (buffer[index++] << 16) + (buffer[index++] << 8) + buffer[index++]; 563 | } 564 | 565 | // common functionality for some derived types 566 | protected void SetAddress (int address, int index) 567 | { 568 | // optimize using local variable 569 | byte[] buffer = this.buffer; 570 | // big endian = most significant byte first 571 | // 3 bytes per address = 24 bits address space 572 | buffer[index++] = (byte)(address >> 16); 573 | buffer[index++] = (byte)(address >> 8); 574 | buffer[index++] = (byte)address; 575 | } 576 | 577 | 578 | #endregion private/protected 579 | } 580 | } 581 | -------------------------------------------------------------------------------- /LibSSM2/Ssm2ReadAddressesRequest.cs: -------------------------------------------------------------------------------- 1 | // Ssm2ReadAddressesRequest.cs: SSM2 packet class for address(es) read request. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | 25 | namespace Subaru.SSM2 26 | { 27 | 28 | /// 29 | /// Packet to retrieve values for individual addresses. 30 | /// This packet type is usually created by the tester and sent to the car control unit. 31 | /// (Consists of 5 byte header + 1 padding + 3 * X addresses + 1 checksum = 7 + 3 * X. 32 | /// Minimum size is 10 for 1 address.) 33 | /// 34 | public sealed class Ssm2ReadAddressesRequest : Ssm2Packet 35 | { 36 | 37 | internal const int DefaultAddressesPerPacket = 36; 38 | static int maxAddresses = DefaultAddressesPerPacket; 39 | 40 | /// 41 | /// Maximum number of addresses to be used for a single packet. 42 | /// Defaults to 36 which most control units from year 2002+ should support. 43 | /// Possible theoretical range: 1 ≤ x ≤ 84. 44 | /// Control unit will not answer when using to many addresses! 45 | /// (Tested ok on modern cars (2008+): ≤ 82, packet size is 253 bytes for 82) 46 | /// (2005 cars might support ≤ 45.) 47 | /// (84 is theoretical limit because of packet length byte) 48 | /// 49 | public static int MaxAddressesPerPacket { 50 | get { return maxAddresses; } 51 | set { 52 | // Net payload = 255 payload length - 1 command byte - 1 padding byte = 253 bytes. 53 | // 253 / 3 = 84.333 => 84 54 | if (value < 1 || value > 84) 55 | throw new ArgumentOutOfRangeException ("value", value, "1 ≤ value ≤ 84"); 56 | maxAddresses = value; 57 | } 58 | } 59 | 60 | /// 61 | /// Calculates packet size for this packet type. 62 | /// 63 | /// 64 | /// Total packet size. 65 | /// 66 | /// 67 | /// Number of addresses to be used. 68 | /// 69 | private static int PacketSize (int addressesCount) 70 | { 71 | return HeaderLength + 2 + 3 * addressesCount; 72 | } 73 | 74 | // require at least one address 75 | private const int PacketSizeSpecificMin = HeaderLength + 2 + 3 * 1; 76 | private const int IndexAddresses = HeaderLength + 1; 77 | 78 | 79 | #region constructors 80 | 81 | public Ssm2ReadAddressesRequest () 82 | { 83 | // base class constructor will be called anyway 84 | this.count = PacketSizeSpecificMin; 85 | } 86 | 87 | public Ssm2ReadAddressesRequest (byte[] buffer) : base (buffer, PacketSizeSpecificMin) 88 | { 89 | } 90 | 91 | /// 92 | /// Constructs a complete packet. 93 | /// (Uses optimal buffer size) 94 | /// 95 | /// 96 | /// A 97 | /// 98 | /// 99 | /// A 100 | /// 101 | /// 102 | /// An 104 | /// 105 | public Ssm2ReadAddressesRequest (Ssm2Device destination, 106 | Ssm2Device source, 107 | IList addresses) 108 | : base (PacketSize (addresses.Count)) 109 | { 110 | this.Destination = destination; 111 | this.Source = source; 112 | // setting Addresses also updates count 113 | this.Addresses = addresses; 114 | 115 | this.propsSet = SetProperties.AllButChecksum; 116 | this.Finish (); 117 | } 118 | 119 | 120 | #endregion constructors 121 | 122 | 123 | // Implementation notes: 124 | // Returning IList instead of IEnumerable because of performance benefits 125 | // for following analysis (e.g. LINQ queries). 126 | 127 | /// 128 | /// Get/set address(es) to request. 129 | /// (SSM2 protocol only uses 24 bits.) 130 | /// Get may return empty list. 131 | /// Set needs at least one item. 132 | /// 133 | public IList Addresses { 134 | get { 135 | int adrCount = AddressesCount; 136 | List addresses = new List (adrCount); 137 | for (int adrNr = 0; adrNr < adrCount; adrNr++) { 138 | addresses.Add (GetAddress (IndexAddresses + 3 * adrNr)); 139 | } 140 | return addresses; 141 | } 142 | set { 143 | if (value == null) 144 | throw new ArgumentNullException (); 145 | int adrCount = value.Count; 146 | if (adrCount <= 0 || adrCount > MaxAddressesPerPacket) 147 | throw new ArgumentOutOfRangeException ("value.Count", adrCount, "1 ≤ x ≤ " + MaxAddressesPerPacket.ToString ()); 148 | 149 | int neededSize = PacketSize (adrCount); 150 | byte[] buf = this.buffer; 151 | if (buf.Length < neededSize) { 152 | // have to allocate bigger buffer and copy header data 153 | byte[] newBuffer = new byte[neededSize]; 154 | Array.Copy (buf, newBuffer, IndexAddresses); 155 | this.buffer = newBuffer; 156 | } 157 | 158 | for (int n = 0; n < adrCount; n++) { 159 | int adr = value[n]; 160 | AssertAddress (adr); 161 | SetAddress (adr, IndexAddresses + 3 * n); 162 | } 163 | 164 | // packet size known here 165 | this.count = neededSize; 166 | UpdateFlags (SetProperties.DataAll); 167 | } 168 | } 169 | 170 | /// 171 | /// Calculates the number of supplied addresses based on packet size. 172 | /// Returns 0 if packet size does not match with expected number of addresses. 173 | /// 174 | public int AddressesCount { 175 | get { 176 | int adrBytes = this.count - HeaderLength - 2; 177 | int adrCount = adrBytes / 3; 178 | return (adrBytes % 3 == 0 && adrCount > 0) ? adrCount : 0; 179 | } 180 | } 181 | 182 | public override bool Check () 183 | { 184 | return this.Command == Ssm2Command.ReadAddressesRequestA8 185 | && base.Check (); 186 | } 187 | 188 | /// 189 | /// Sets specific packet bytes. 190 | /// 191 | protected override void SetConstBytes () 192 | { 193 | base.Command = Ssm2Command.ReadAddressesRequestA8; 194 | // 6th byte, following header, is padding 0x00 195 | buffer[HeaderLength] = 0; 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /LibSSM2/Ssm2ReadAddressesResponse.cs: -------------------------------------------------------------------------------- 1 | // Ssm2ReadAddressesResponse.cs: SSM2 packet class for address(es) read response. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | 25 | namespace Subaru.SSM2 26 | { 27 | 28 | /// 29 | /// This packet type is usually created by the car control unit and sent to the tester. 30 | /// Example: 0x80 0xF0 0x10 0x03 0xE8 0x7D 0xB1 0x99 31 | /// 32 | public sealed class Ssm2ReadAddressesResponse : Ssm2DataResponse, ISsm2Packet 33 | { 34 | #region constructors 35 | 36 | public Ssm2ReadAddressesResponse () : base() 37 | { 38 | } 39 | 40 | public Ssm2ReadAddressesResponse (byte[] buffer) : base(buffer) 41 | { 42 | } 43 | 44 | /// 45 | /// Constructs a complete packet. 46 | /// (Uses optimal buffer size) 47 | /// 48 | /// 49 | /// Destination ID. 50 | /// 51 | /// 52 | /// Source ID. 53 | /// 54 | /// 55 | /// Data bytes. 56 | /// 57 | public Ssm2ReadAddressesResponse (Ssm2Device destination, Ssm2Device source, IList data) : base(destination, source, data) 58 | { 59 | this.Finish (); 60 | } 61 | 62 | #endregion constructors 63 | 64 | 65 | public override bool Check () 66 | { 67 | return this.Command == Ssm2Command.ReadAddressesResponseE8 && base.Check (); 68 | } 69 | 70 | protected override void SetConstBytes () 71 | { 72 | base.Command = Ssm2Command.ReadAddressesResponseE8; 73 | // no padding byte 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /LibSSM2/Ssm2ReadBlockRequest.cs: -------------------------------------------------------------------------------- 1 | // Ssm2ReadBlockRequest.cs: SSM2 packet class for block read request. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | 25 | namespace Subaru.SSM2 26 | { 27 | 28 | /// 29 | /// Read a block of data. 30 | /// Specific properties are starting address and data count. 31 | /// This packet type is usually created by the tester and sent to the car control unit. 32 | /// Always consists of 11 bytes: 5 header + 1 padding + 3 address + 1 count + 1 checksum byte. 33 | /// 34 | public sealed class Ssm2ReadBlockRequest : Ssm2Packet 35 | { 36 | private const int PacketSizeSpecificFixed = HeaderLength + 1 + 3 + 1 + 1; 37 | private const int IndexAddress = HeaderLength + 1; 38 | private const int IndexDataCount = IndexAddress + 3; 39 | 40 | #region constructors 41 | 42 | /// 43 | /// Creates an empty block read packet. 44 | /// (Allocated optimal 11 bytes buffer.) 45 | /// 46 | public Ssm2ReadBlockRequest () : base (PacketSizeSpecificFixed) 47 | { 48 | // this type of packet has fixed length so it can be set once here 49 | this.count = PacketSizeSpecificFixed; 50 | } 51 | 52 | /// 53 | /// Takes given (empty or preset) buffer. 54 | /// Needs at least 11 bytes. 55 | /// For already preset packet data call FromBytes(buffer) 56 | /// afterwards to set correct state. 57 | /// 58 | /// 59 | /// A 60 | /// 61 | public Ssm2ReadBlockRequest (byte[] buffer) : base (buffer, PacketSizeSpecificFixed) 62 | { 63 | } 64 | 65 | /// 66 | /// Creates a complete packet. 67 | /// (Will have optimal buffer length.) 68 | /// 69 | public Ssm2ReadBlockRequest (Ssm2Device destination, 70 | Ssm2Device source, 71 | int address, 72 | byte dataCount) : base (PacketSizeSpecificFixed) 73 | { 74 | this.Destination = destination; 75 | this.Source = source; 76 | this.Address = address; 77 | this.DataCount = dataCount; 78 | this.Finish (); 79 | } 80 | 81 | 82 | #endregion constructors 83 | 84 | public int Address { 85 | get { 86 | return GetAddress (IndexAddress); 87 | } 88 | set { 89 | AssertAddress (value); 90 | SetAddress (value, IndexAddress); 91 | UpdateFlags (SetProperties.Data1); 92 | } 93 | } 94 | 95 | /// 96 | /// Number of bytes to request. 97 | /// (Corresponding packet byte = count - 1 ! 98 | /// E.g. packet byte 0x00 means 1 byte.) 99 | /// 100 | public byte DataCount { 101 | get { return (byte)(buffer[IndexDataCount] + 1); } 102 | set { 103 | buffer[IndexDataCount] = (byte)(value - 1); 104 | UpdateFlags (SetProperties.Data2 | SetProperties.Data3); 105 | } 106 | } 107 | 108 | public override bool Check () 109 | { 110 | return this.Command == Ssm2Command.ReadBlockRequestA0 111 | && this.count == PacketSizeSpecificFixed 112 | && base.Check (); 113 | } 114 | 115 | /// 116 | /// Create a complete packet out of supplied data. 117 | /// 118 | protected override void SetConstBytes () 119 | { 120 | base.Command = Ssm2Command.ReadBlockRequestA0; 121 | // 6th byte, following header, is padding = 0 122 | buffer[HeaderLength] = 0; 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /LibSSM2/Ssm2ReadBlockResponse.cs: -------------------------------------------------------------------------------- 1 | // Ssm2ReadBlockResponse.cs: SSM2 packet class for block read response. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | 25 | namespace Subaru.SSM2 26 | { 27 | 28 | /// 29 | /// Returns requested data of a previous read-block-request. 30 | /// This packet type is usually created by the car control unit and sent to the tester. 31 | /// Example containing 3 data bytes: { 0x80, 0xF0, 0x10, 0x04, 0xE0, 0x01, 0x02, 0x03, 0x6A }. 32 | /// 33 | public sealed class Ssm2ReadBlockResponse : Ssm2DataResponse 34 | { 35 | #region constructors 36 | 37 | public Ssm2ReadBlockResponse () : base () 38 | { 39 | } 40 | 41 | public Ssm2ReadBlockResponse (byte[] buffer) : base (buffer) 42 | { 43 | } 44 | 45 | public Ssm2ReadBlockResponse (Ssm2Device destination, 46 | Ssm2Device source, 47 | IList data) 48 | : base (destination, source, data) 49 | { 50 | } 51 | 52 | #endregion constructors 53 | 54 | public override bool Check () 55 | { 56 | return this.Command == Ssm2Command.ReadBlockResponseE0 57 | && base.Check (); 58 | } 59 | 60 | protected override void SetConstBytes () 61 | { 62 | base.Command = Ssm2Command.ReadBlockResponseE0; 63 | // no padding 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /LibSSM2/Ssm2WriteAddressRequest.cs: -------------------------------------------------------------------------------- 1 | // Ssm2WriteAddressRequest.cs: SSM2 packet class for address write request. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | 25 | namespace Subaru.SSM2 26 | { 27 | 28 | /// 29 | /// Write a single byte into an address. 30 | /// This packet type is usually created by the tester and sent to the car control unit. 31 | /// (Packet always consists of 10 bytes: 5 byte header + 3 address bytes + 1 data byte + 1 checksum.) 32 | /// 33 | public sealed class Ssm2WriteAddressRequest : Ssm2Packet 34 | { 35 | /// 36 | /// Packet always consists of 10 bytes: 5 byte header + 3 address bytes + 1 data byte + 1 checksum. 37 | /// 38 | private const int PacketSizeSpecificFixed = HeaderLength + 3 + 1 + 1; 39 | 40 | #region constructors 41 | 42 | public Ssm2WriteAddressRequest () 43 | { 44 | // base class constructor will be called anyway 45 | // : base() 46 | // this type of packet has fixed length 47 | this.count = PacketSizeSpecificFixed; 48 | } 49 | 50 | public Ssm2WriteAddressRequest (byte[] buffer) 51 | : base (buffer, PacketSizeSpecificFixed) 52 | { 53 | } 54 | 55 | /// 56 | /// Uses optimal buffer size. 57 | /// 58 | /// 59 | /// A 60 | /// 61 | /// 62 | /// A 63 | /// 64 | /// 65 | /// A 66 | /// 67 | public Ssm2WriteAddressRequest (Ssm2Device destination, 68 | Ssm2Device source, 69 | int address, 70 | byte data) 71 | : base (PacketSizeSpecificFixed) 72 | { 73 | this.count = PacketSizeSpecificFixed; 74 | this.Destination = destination; 75 | this.Source = source; 76 | this.Address = address; 77 | this.Data = data; 78 | } 79 | 80 | 81 | #endregion constructors 82 | 83 | public int Address { 84 | get { 85 | return GetAddress (HeaderLength); 86 | } 87 | set { 88 | AssertAddress (value); 89 | SetAddress (value, HeaderLength); 90 | UpdateFlags (SetProperties.Data1); 91 | } 92 | } 93 | 94 | public byte Data { 95 | get { return this.buffer[HeaderLength + 3]; } 96 | set { 97 | this.buffer[HeaderLength + 3] = value; 98 | UpdateFlags (SetProperties.Data2 | SetProperties.Data3); 99 | } 100 | } 101 | 102 | public override bool Check () 103 | { 104 | return this.Command == Ssm2Command.WriteAddressRequestB8 105 | && this.count == PacketSizeSpecificFixed 106 | && base.Check (); 107 | } 108 | 109 | protected override void SetConstBytes () 110 | { 111 | // 5th byte = command 112 | base.Command = Ssm2Command.WriteAddressRequestB8; 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /LibSSM2/Ssm2WriteAddressResponse.cs: -------------------------------------------------------------------------------- 1 | // Ssm2WriteAddressResponse.cs: SSM2 packet class for address write response. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | 25 | namespace Subaru.SSM2 26 | { 27 | 28 | /// 29 | /// Response packet of a write-address-request. 30 | /// Contains a single byte confirming the written byte. 31 | /// This packet type is usually created by the tester and sent to the car control unit. 32 | /// Example confirming data byte 0x02: { 0x80, 0xF0, 0x10, 0x02, 0xF8, 0x02, 0x7C } 33 | /// 34 | public sealed class Ssm2WriteAddressResponse : Ssm2Packet 35 | { 36 | /// 37 | /// Packet always consists of 7 bytes: 5 byte header + 1 data byte + 1 checksum. 38 | /// 39 | private const int PacketSizeSpecificFixed = HeaderLength + 1 + 1; 40 | 41 | 42 | #region constructors 43 | 44 | /// 45 | /// Uses optimal buffer size. 46 | /// 47 | public Ssm2WriteAddressResponse () : base (PacketSizeSpecificFixed) 48 | { 49 | // this type of packet has fixed length so it can be set once here 50 | this.count = PacketSizeSpecificFixed; 51 | } 52 | 53 | /// 54 | /// Takes given (empty or preset) buffer. 55 | /// Needs at least 7 bytes. 56 | /// For already preset packet data call FromBytes(buffer) afterwards to set correct state. 57 | /// 58 | /// 59 | /// A 60 | /// 61 | public Ssm2WriteAddressResponse (byte[] buffer) 62 | : base (buffer, PacketSizeSpecificFixed) 63 | { 64 | } 65 | 66 | /// 67 | /// Uses optimal buffer size. 68 | /// 69 | /// 70 | /// A 71 | /// 72 | /// 73 | /// A 74 | /// 75 | /// 76 | /// A 77 | /// 78 | public Ssm2WriteAddressResponse (Ssm2Device destination, 79 | Ssm2Device source, 80 | byte data) 81 | : this () 82 | { 83 | this.Destination = destination; 84 | this.Source = source; 85 | this.Data = data; 86 | 87 | this.Finish(); 88 | } 89 | 90 | 91 | #endregion constructors 92 | 93 | 94 | public byte Data { 95 | get { 96 | return this.buffer[HeaderLength]; 97 | } 98 | set { 99 | this.buffer[HeaderLength] = value; 100 | UpdateFlags (SetProperties.DataAll); 101 | } 102 | } 103 | 104 | public override bool Check () 105 | { 106 | return this.Command == Ssm2Command.WriteAddressResponseF8 107 | && this.count == PacketSizeSpecificFixed 108 | && base.Check (); 109 | } 110 | 111 | protected override void SetConstBytes () 112 | { 113 | base.Command = Ssm2Command.WriteAddressResponseF8; 114 | // no padding byte 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | CONTENT 2 | ======= 3 | 1 License 4 | 2 Purpose 5 | 3 SSM2 Protocol Overview 6 | 4 Platforms 7 | 5 Dependencies 8 | 6 Compilation 9 | 7 Contribute 10 | 8 Implementation Notes 11 | 9 Links 12 | 13 | 14 | 1) License 15 | ========== 16 | GPL3. See text file COPYING.txt for details. 17 | 18 | 19 | 2) Purpose 20 | ========== 21 | LibSSM2 is a .NET library providing functionality for the SSM2 22 | (Subaru Select Monitor 2) protocol. 23 | Most importantly the packet classes know how to create and parse SSM2 packets. 24 | The consumer code therefore can concentrate on the payload data itself. 25 | Currently 8 out of 10 well known SSM2 packet types are implemented in the code. 26 | 27 | Although there are several OSS projects using SSM2 internally, 28 | I did not like most implementations and/or the additional work 29 | required for filtering out the actual SSM2 protocol stuff. 30 | So I wrote my own code from scratch the way I think it should be - 31 | implented as a lean independent library. 32 | 33 | To actually make use of this library you'll need an appropriate 34 | hardware interface (typically standard OBD-II port on the car, 35 | serial or USB port for computer) plus additional code and knowledge 36 | in order to send and receive data (in the form of SSM2 packets) via interface. 37 | 38 | Application code using this library has been tested with several 39 | hardware interfaces on various operating systems. 40 | 41 | Sooner or later, depending on spare time, I will also publish application code. 42 | 43 | 44 | 3) SSM2 Protocol Overview 45 | ========================= 46 | SSM2 is a special car diagnostic protocol. 47 | For details see text file SSM2_Protocol.txt. 48 | As far as I know it is only being used by Subaru (c) cars. 49 | Subaru is a trademark of Fuji Heavy Industries Ltd (FHI). 50 | SSM2 operates at 4800 baud and is being used by (original) 51 | Subaru cars from 2001+ (?). 52 | Earlier models may use SSM1, a very different protocol, using 1953 baud. 53 | 54 | 55 | 4) Platforms 56 | ============ 57 | The code is platform independent pure C#, 58 | compliant with the Common Language Specification (CLS). 59 | Originally created with MonoDevelop on Linux. 60 | Should run on any operating system provided that a .NET compatible 61 | runtime is available. 62 | Translating this C# code into C++ or many other languages should be fairly easy. 63 | 64 | 65 | 5) Dependencies 66 | =============== 67 | Currently the code only needs a .NET Framework v2.0 compatible runtime 68 | and base class assemblies. 69 | It only references mscorlib.dll. 70 | More recent C# language features may be used to allow modern/short syntax, 71 | so a .NET v3+ compiler might be necessary. 72 | 73 | 74 | 6) Compilation 75 | ============== 76 | Visual Studio (2008) solution (.sln) and C# project (.csproj) files were 77 | generated by integrated development environment (IDE) MonoDevelop 2.4+. 78 | Microsoft VS2010 (and possibly other .NET IDEs) should be able to open these. 79 | 80 | This solution contains two projects in separate subfolders: 81 | 1) LibSSM2: actual LibSSM2 code 82 | 2) TestLibSSM2: NUnit tests in a separate DLL 83 | 84 | Here are methods to compile with command line tools, especially if 85 | you don't have an IDE installed. 86 | 87 | 88 | mono (Linux at least) 89 | --------------------- 90 | Tested on Linux x64. 91 | You need to have some mono/mono-core packages installed. 92 | 93 | a) Using xbuild (XBuild Engine, compatible to Microsoft MSBUILD) 94 | Usually xbuild is available by Linux package "mono-devel". 95 | 96 | Examples: 97 | 98 | (will create Debug configuration by default) 99 | xbuild 100 | 101 | xbuild /property:Configuration=Debug 102 | 103 | xbuild /property:Configuration=Release 104 | 105 | xbuild LibSSM2.sln 106 | 107 | xbuild LibSSM2/LibSSM2.csproj /property:Configuration=Release 108 | 109 | 110 | b) Using gmcs (Mono C# compiler) directly 111 | 112 | The manual page for "gmcs" says: 113 | "The Mono C# compiler by default only references three assemblies: 114 | mscorlib.dll, System.dll and System.Xml.dll." 115 | 116 | Now to compile the actual library from source files: 117 | 118 | .../LibSSM2> cd LibSSM2 119 | .../LibSSM2/LibSSM2> gmcs -out:bin/Release/LibSSM2.dll -target:library *.cs 120 | 121 | If all went well the resulting library file should exist, roughly 14 KiB: 122 | bin/Release/LibSSM2.dll 123 | Most IDEs use bin/Debug and bin/Release subdirs for output. 124 | 125 | 126 | Advanced stuff: 127 | Mono Ahead-of-Time compilation (AOT), creating file LibSSM2.dll.so: 128 | mono --aot=full --optimize=all LibSSM2.dll 129 | 130 | Decompile AOT native code: 131 | objdump -d LibSSM2.dll.so > LibSSM2_aot.asm 132 | Use Intel syntax instead of default (AT&T): 133 | objdump -d LibSSM2.dll.so --disassembler-options=intel > LibSSM2_aot.masm 134 | 135 | 136 | Windows 137 | ------- 138 | 139 | C# compiler CSC.exe usually ships with modern Windows OS 140 | (Vista or later) as these versions already have a .NET Framework installed. 141 | 142 | There is a free Windows SDK downloadable from Microsoft, providing 143 | additional tools and documentation. 144 | Also free is the full integrated development environment (IDE) 145 | "Visual Studio, Express Edition". 146 | 147 | When you use additional stuff like SDK or VS, you can use 148 | "SDK Command Prompt" or "Visual Studio Command Prompt" etc. as these 149 | shortcuts provide paths to needed executables like csc.exe or msbuild.exe. 150 | 151 | If you don't want to install any tool I recommend creating a .BAT file 152 | where you can easily type the needed paths once. 153 | 154 | 155 | a) Using MSBUILD (Microsoft (R) Build Engine) 156 | 157 | With special command prompts, to compile the whole solution or just the 158 | main project: 159 | 160 | msbuild LibSSM2.sln 161 | 162 | msbuild LibSSM2\LibSSM2.csproj 163 | 164 | 165 | 166 | Sample content for a .BAT file using full paths: 167 | ----- 168 | REM with .NET framework 4 (full) installed: 169 | REM where msbuild 170 | REM e.g.: 171 | REM C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe 172 | REM C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe 173 | 174 | SET MSBUILDPATH="C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" 175 | 176 | REM solution or project file 177 | REM SET INPUT="LibSSM2\LibSSM2.csproj" 178 | SET INPUT="LibSSM2.sln" 179 | 180 | %MSBUILDPATH% %INPUT% 181 | ----- 182 | 183 | 184 | b) Using CSC (Microsoft (R) Visual C# 2010 Compiler) directly 185 | 186 | By default, optimizations are disabled. Specify /optimize+ to enable optimizations. 187 | 188 | csc.exe is sufficient Command Prompt" or similar 189 | csc /out:C:\LibSSM2.dll /target:library /optimize LibSSM2\*.cs 190 | 191 | 192 | Sample content for a .BAT file using full paths: 193 | ----- 194 | REM with .NET framework 4 (full) installed: 195 | REM where csc 196 | REM "C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\csc.exe" 197 | REM "C:\WINDOWS\Microsoft.NET\Framework\v3.5\csc.exe" 198 | 199 | REM Full path needed to allow being run from plain normal command prompt. 200 | 201 | REM Just csc.exe is sufficient when using SDK Command Prompt or similar. 202 | REM This would execute latest installed (e.g. v4) .NET C# compiler. 203 | 204 | SET CSCPATH="C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\csc.exe" 205 | 206 | SET INPUT="LibSSM2\*.cs" 207 | SET OUTPUT="LibSSM2\bin\Release\LibSSM2.dll" 208 | 209 | %CSCPATH% /out:%OUTPUT% /target:library /optimize %INPUT% 210 | ----- 211 | 212 | 213 | 214 | 7) Contribute 215 | ============= 216 | Any contributions, notes, hints, bug reports etc. are welcome. 217 | Code formatting: MonoDevelop style "Mono", Unix line endings, 218 | standard 8 char tabs. 219 | Some very long lines have been broken manually since 220 | MonoDevelop feature "Edit|Format|Format Document" won't do it. 221 | There is a simple Linux script "clean_whitespace.sh" 222 | useful to remove trailing whitespace before committing. 223 | 224 | 225 | 8) Implementation Notes 226 | ======================= 227 | 228 | Design goals 229 | ------------ 230 | Hopefully at least partially accomplished: 231 | 232 | 1) lean and efficient 233 | 2) reliable, especially for standard use cases 234 | 3) usable on limited Mono/.NET installations 235 | (i.e. Compact Framework devices like PocketPC) 236 | 4) easy to use, requiring only basic SSM2 protocol knowledge 237 | 238 | 239 | A perfect achievement of all these topics, e.g. highly efficient and 240 | very safe to use, may not be fully possible. 241 | These Subaru SSM2 packet classes are designed for object reusability which means 242 | these objects are immutable. 243 | Properties can be changed and will only affect corresponding packet bytes. 244 | I.e. once header info has been set, one can modify payload data, 245 | unchanged header bytes don't have to be rewritten. 246 | This implementation also avoids many backing fields as most properties directly 247 | rely on underlying packet buffer bytes. As an added benefit consistency problems 248 | between properties and actual packet bytes should not occur. 249 | 250 | 251 | Optimization 252 | ------------ 253 | Some C# compiler observations confirmed by tool "Reflector": 254 | Applies to both Mono (2.6.4) and Windows .NET (4) C# compilers, 255 | with optimizations turned on. 256 | These things don't really matter here as SSM2 uses a slow data rate 257 | but could be useful somewhere else. 258 | 259 | a) Simple calculation subtracting a field by two constants: 260 | int dataCount = this.count - HeaderLength - 1; 261 | 262 | --> int num = (base.count - 5) - 1; 263 | This is not optimal, uses two subtractions instead of one. 264 | 265 | Even Mono full AOT compilation (on x64 at least) does not optimize 266 | this inefficient IL away: 267 | 268 | 00000000000012b0 : 269 | 12b0: 48 83 ec 08 sub rsp,0x8 270 | 12b4: 4c 89 3c 24 mov QWORD PTR [rsp],r15 271 | 12b8: 4c 8b ff mov r15,rdi 272 | 12bb: 49 63 47 18 movsxd rax,DWORD PTR [r15+0x18] 273 | 12bf: 83 e8 05 sub eax,0x5 274 | 12c2: 4c 8b f8 mov r15,rax 275 | 12c5: 41 ff cf dec r15d 276 | 12c8: 41 83 ff 01 cmp r15d,0x1 277 | 12cc: 7c 0e jl 12dc 278 | 12ce: 41 81 ff fe 00 00 00 cmp r15d,0xfe 279 | 12d5: 7f 05 jg 12dc 280 | 12d7: 49 8b c7 mov rax,r15 281 | 12da: eb 02 jmp 12de 282 | 12dc: 33 c0 xor eax,eax 283 | 12de: 4c 8b 3c 24 mov r15,QWORD PTR [rsp] 284 | 12e2: 48 83 c4 08 add rsp,0x8 285 | 12e6: c3 ret 286 | 287 | 288 | Solution: 289 | Grouping constants together yields expected 290 | smaller/better IL code - 1 subtraction only: 291 | int dataCount = this.count - (HeaderLength + 1); 292 | --> int num = base.count - 6; 293 | 294 | Native code of course gets slightly better as well: 295 | 00000000000012b0 : 296 | 12b0: 48 83 ec 08 sub rsp,0x8 297 | 12b4: 4c 89 3c 24 mov QWORD PTR [rsp],r15 298 | 12b8: 4c 8b ff mov r15,rdi 299 | 12bb: 49 63 47 18 movsxd rax,DWORD PTR [r15+0x18] 300 | 12bf: 4c 8b f8 mov r15,rax 301 | 12c2: 41 83 ef 06 sub r15d,0x6 302 | 12c6: 41 83 ff 01 cmp r15d,0x1 303 | 12ca: 7c 0e jl 12da 304 | 12cc: 41 81 ff fe 00 00 00 cmp r15d,0xfe 305 | 12d3: 7f 05 jg 12da 306 | 12d5: 49 8b c7 mov rax,r15 307 | 12d8: eb 02 jmp 12dc 308 | 12da: 33 c0 xor eax,eax 309 | 12dc: 4c 8b 3c 24 mov r15,QWORD PTR [rsp] 310 | 12e0: 48 83 c4 08 add rsp,0x8 311 | 12e4: c3 ret 312 | 313 | 314 | b) Windows .NET CSC uses short versions of some IL instructions: 315 | Requiring 2 IL bytes: blt.s L_0015 316 | while Mono compiler gmcs does not: 317 | Requiring 5 IL bytes: blt L_001b 318 | The behavior is exactly the same, the DLL will be slightly larger though. 319 | 320 | 321 | Multi-threading 322 | --------------- 323 | No special support is built in (no locks etc.) as this code has 324 | no knowledge where it will be used. 325 | Thread safety must be taken into account in the application 326 | at a higher level if needed. 327 | 328 | 329 | 9) Links 330 | ======== 331 | 332 | About Subaru 333 | ------------ 334 | http://en.wikipedia.org/wiki/Subaru 335 | http://www.subaru-global.com/ 336 | 337 | 338 | ecuExplorer 339 | ----------- 340 | "ecuExplorer is an open-source application that will connect to a Subaru ECU" 341 | C++, GPL2 license 342 | http://code.google.com/p/ecuexplorer/ 343 | 344 | 345 | .NET SSM 346 | -------- 347 | C# .NET, SSM2, GPL(?) license; library, tools and CarPC software 348 | http://ssm.codeplex.com/ 349 | 350 | 351 | FreeSSM 352 | ------- 353 | C++ Qt4, GPL3 license, SSM2 (SSM1 will be added soon?) 354 | http://freessm.berlios.de/ 355 | 356 | -------------------------------------------------------------------------------- /SSM2_Protocol.txt: -------------------------------------------------------------------------------- 1 | >--------------------------------------------------------- 2 | IMPORTANT: 3 | This document (probably) originates from the 4 | ecuExplorer project, GPL2, filename "ssm.pdf" 5 | written by Calvin Cestari (?) 6 | Source: http://code.google.com/p/ecuexplorer/ 7 | 8 | It can also be found in RomRaider SVN: 9 | trunk/docs/logger/ssm_info.txt 10 | 11 | Apparently this documentation has not been updated for a long time. 12 | Especially modern cars do provide much more ECU Init flagbytes. 13 | The whole protocol description itself is still valid. 14 | Although the content does not tell about SSM versions, all content 15 | applies to SSM2 only. Older protocols like SSM1 are very different. 16 | >--------------------------------------------------------- 17 | 18 | 19 | The subaru select monitor protocol uses an ISO9141 interface and uses UART settings: 4800 bps n, 8, 1 20 | All data is sent and recieved using small packets that all share a common header. 21 | 22 | 23 | 24 | Packets all follow this structure: 25 | 26 | 0x80 27 | Destination byte 28 | Source byte 29 | Data Size byte 30 | data... 31 | ... 32 | Checksum byte 33 | 34 | Known Destination and Source bytes respectively: 35 | 0x10 Subaru ECU 36 | 0xF0 Diagnostic tool 37 | 38 | The Data Size byte specifies the number of data bytes in the packet, the Checksum byte is the 8 least significant 39 | bits of the sum of every packet byte (including the header) 40 | 41 | For example: 42 | 43 | If you send the packet: 44 | 45 | 0x80 0x10 0xF0 0x01 0xBF 0x40 46 | 47 | the ecu might respond with: 48 | 0x80 0xF0 0x10 0x39 0xFF 0xA2 0x10 0x0F 0x1B 0x14 0x40 0x05 0x05 0x73 0xFA 0xEB 49 | 0x80 0x2B 0xC1 0x02 0xAA 0x00 0x10 0x00 0x60 0xCE 0x54 0xF8 0xB0 0x60 0x00 0x00 50 | 0xE0 0x00 0x00 0x00 0x00 0x00 0xDC 0x00 0x00 0x55 0x10 0x00 0x00 0x02 0x00 0x00 51 | 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x1F 52 | 53 | 54 | When sending a packet to the ECU the first data byte is the command byte. 55 | These are the known commands: 56 | 57 | 0xA0 Read memory 58 | 0xA8 Read single address 59 | 0xB0 Write memory 60 | 0xB8 Write single address 61 | 0xBF ECU init 62 | 63 | 64 | -------------------------------- Command Formats -------------------------------- 65 | 66 | A0 Block Read Request 67 | 68 | A0 PP AA AA AA CC 69 | 70 | PP == pad? 71 | AA AA AA = address 72 | CC == byte count - 1 73 | 74 | A8 Address Read Request 75 | 76 | A8 PP A1 A1 A1 A2 A2 A2 A3 A3 A3... 77 | 78 | PP == pad? 79 | A1 A1 A1 == address 80 | A2 A2 A2 ... == optional addresses 81 | 82 | B0 Write Block Request 83 | 84 | B0 AA AA AA DD DD DD DD DD ... 85 | 86 | AA AA AA == address 87 | DD DD ... == data of desired length 88 | 89 | B8 Address Write Request 90 | 91 | B8 AA AA AA DD 92 | 93 | AA AA AA == address 94 | DD == data byte 95 | 96 | BF ECU Init Request 97 | 98 | BF 99 | 100 | -------------------------------- Command Examples ------------------------------- 101 | 102 | Block Read: Read 128 bytes from address 0x200000 (ecu returned all zeros) 103 | 104 | Sent: 105 | 0x80 0x10 0xF0 0x06 0xA0 0x00 0x20 0x00 0x00 0x7F 0xC5 106 | 107 | Received: 108 | 0x80 0xF0 0x10 0x81 0xE0 109 | 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 110 | 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 111 | 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 112 | 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 113 | 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 114 | 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 115 | 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 116 | 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 117 | 0xE1 118 | 119 | ----------------------- 120 | 121 | Address Read: Read Address 0x000008 and 0x00001C (ecu returns values 0x7D and 0xB1) 122 | 123 | Sent: 124 | 0x80 0x10 0xF0 0x08 0xA8 0x00 0x00 0x00 0x08 0x00 0x00 0x1C 0x54 125 | 126 | Received: 127 | 0x80 0xF0 0x10 0x03 0xE8 0x7D 0xB1 0x99 128 | 129 | ----------------------- 130 | 131 | Block Write: Write 4 bytes to address 0x200000 (ecu returns written data) 132 | 133 | Sent: 134 | 0x80 0x10 0xF0 0x08 0xB0 0x20 0x00 0x00 0x01 0x02 0x03 0x04 0x62 135 | 136 | Received: 137 | 0x80 0xF0 0x10 0x05 0xF0 0x01 0x02 0x03 0x04 0x7F 138 | 139 | ----------------------- 140 | 141 | Write single address: Write value 0x02 to address 0x00006F 142 | 143 | Sent: 144 | 0x80 0x10 0xF0 0x05 0xB8 0x00 0x00 0x6F 0x02 0xAE 145 | 146 | Received: 147 | 0x80 0xF0 0x10 0x02 0xF8 0x02 0x7C 148 | 149 | ---------------------------------------------------------------------------------- 150 | 151 | Certain bytes in the ECU Init string (returned from request 0xBF) can be examined to determine which parameters the ECU will support. 152 | The individual bits are flags that will be set to one if the parameter can be read from the ECU (byte 9 is immediately after the 5 byte ECU ID value) 153 | ********** BYTE 9 ********** 154 | 7 Engine Load 155 | 6 Coolant Temperature 156 | 5 Air/Fuel Correction #1 157 | 4 Air/Fuel Learning #1 158 | 3 Air/Fuel Correction #2 159 | 2 Air/Fuel Learning #2 160 | 1 Manifold Absolute Pressure 161 | 0 Engine Speed 162 | 163 | ********** BYTE 10 ********* 164 | 7 Vehicle Speed 165 | 6 Ignition Timing 166 | 5 Intake Air Temperature 167 | 4 Mass Air Flow 168 | 3 Throttle Opening Angle 169 | 2 Front O2 Sensor #1 170 | 1 Rear O2 Sensor 171 | 0 Front O2 Sensor #2 172 | 173 | ********** BYTE 11 ********* 174 | 7 Battery Voltage 175 | 6 Air Flow Sensor Voltage 176 | 5 Throttle Sensor Voltage 177 | 4 Differential Pressure Sensor Voltage 178 | 3 Fuel Injection #1 Pulse Width 179 | 2 Fuel Injection #2 Pulse Width 180 | 1 Knock Correction 181 | 0 Atmospheric Pressure 182 | 183 | ********** BYTE 12 ********** 184 | 7 Manifold Relative Pressure 185 | 6 Pressure Differential Sensor 186 | 5 Fuel Tank Pressure 187 | 4 CO Adjustment 188 | 3 Learned Ignition Timing 189 | 2 Accelerator Opening Angle 190 | 1 Fuel Temperature 191 | 0 Front O2 Heater #1 192 | 193 | ********** BYTE 13 ********* 194 | 7 Rear O2 Heater Current 195 | 6 Front O2 Heater #2 196 | 5 Fuel Level 197 | 4 ------------------------- 198 | 3 Primary Wastegate Duty Cycle 199 | 2 Secondary Wastegate Duty Cycle 200 | 1 CPC Valve Duty Ratio 201 | 0 Tumble Valve Position Sensor Right 202 | 203 | ********** BYTE 14 ********* 204 | 7 Tumble Valve Position Sensor Left 205 | 6 Idle Speed Control Valve Duty Ratio 206 | 5 Air/Fuel Lean Correction 207 | 4 Air/Fuel Heater Duty 208 | 3 Idle Speed Control Valve Step 209 | 2 Number of Ex. Gas Recirc Steps 210 | 1 Alternator Duty 211 | 0 Fuel Pump Duty 212 | 213 | ********** BYTE 15 ********* 214 | 7 VVT Advance Angle Right 215 | 6 VVT Advance Angle Left 216 | 5 OCV Duty Right 217 | 4 OCV Duty Left 218 | 3 OCV Current Right 219 | 2 OCV Current Left 220 | 1 Air/Fuel Sensor #1 Current 221 | 0 Air/Fuel Sensor #2 Current 222 | 223 | ********** BYTE 16 ********** 224 | 7 Air/Fuel Sensor #1 Resistance 225 | 6 Air/Fuel Sensor #2 Resistance 226 | 5 Air/Fuel Sensor #1 227 | 4 Air/Fuel Sensor #2 228 | 3 Air/Fuel Correction #3 229 | 2 Air/Fuel Learning #3 230 | 1 Rear O2 Heater Voltage 231 | 0 Air/Fuel Adjustment Voltage 232 | 233 | ********** BYTE 17 ********** 234 | 7 ------------------------- 235 | 6 ------------------------- 236 | 5 Gear Position 237 | 4 ------------------------- 238 | 3 ------------------------- 239 | 2 ------------------------- 240 | 1 ------------------------- 241 | 0 ------------------------- 242 | 243 | ********** BYTE 18 ********** 244 | 7 ------------------------- 245 | 6 ------------------------- 246 | 5 ------------------------- 247 | 4 Air/Fuel Sensor #1 Heater Current 248 | 3 Air/Fuel Sensor #2 Heater Current 249 | 2 ------------------------- 250 | 1 ------------------------- 251 | 0 ------------------------- 252 | 253 | ********** BYTE 19 ********** 254 | 7 ------------------------- 255 | 6 ------------------------- 256 | 5 ------------------------- 257 | 4 ------------------------- 258 | 3 ------------------------- 259 | 2 ------------------------- 260 | 1 ------------------------- 261 | 0 ------------------------- 262 | 263 | ********** BYTE 20 ********** 264 | 7 ------------------------- 265 | 6 AT Vehicle ID 266 | 5 Test Mode Connector 267 | 4 Read Memory Connector 268 | 3 ------------------------- 269 | 2 ------------------------- 270 | 1 ------------------------- 271 | 0 ------------------------- 272 | ********** BYTE 21 ********** 273 | 7 Neutral Position Switch 274 | 6 Idle Switch 275 | 5 ------------------------- 276 | 4 Intercooler AutoWash Switch 277 | 3 Ignition Switch 278 | 2 Power Steering Switch 279 | 1 Air Conditioning Switch 280 | 0 ------------------------- 281 | ********** BYTE 22 ********** 282 | 7 Handle Switchv 283 | 6 Starter Switch 284 | 285 | 5 Front O2 Rich Signal 286 | 4 Rear O2 Rich Signal 287 | 288 | 3 Front O2 #2 Rich Signal 289 | 2 Knock Signal 1 290 | 1 Knock Signal 2 291 | 0 Electrical Load Signal 292 | ********** BYTE 23 ********** 293 | 7 Crank Position Sensor 294 | 6 Cam Position Senso 295 | 5 Defogger Switch 296 | 4 Blower Switch 297 | 3 Interior Light Switch 298 | 2 Wiper Switch 299 | 1 Air-Con Lock Signal 300 | 0 Air-Con Mid Pressure Switch 301 | 302 | ********** BYTE 24 ********** 303 | 7 Air-Con Compressor Signal 304 | 6 Radiator Fan Relay #3 305 | 5 Radiator Fan Relay #1 306 | 4 Radiator Fan Relay #2 307 | 3 Fuel Pump Relay 308 | 2 Intercooler Auto-Wash Relay 309 | 1 CPC Solenoid Valve 310 | 0 Blow-By Leak Connector 311 | 312 | ********** BYTE 25 ********** 313 | 7 PCV Solenoid Valve 314 | 6 TGV Output 315 | 5 TGV Drive 316 | 4 Variable Intake Air Solenoid 317 | 3 Pressure Sources Change 318 | 2 Vent Solenoid Valve 319 | 1 P/S Solenoid Valve 320 | 0 Assist Air Solenoid Valve 321 | 322 | ********** BYTE 26 ********** 323 | 7 Tank Sensor Control Valve 324 | 6 Relief Valve Solenoid 1 325 | 5 Relief Valve Solenoid 2 326 | 4 TCS Relief Valve Solenoid 327 | 3 Ex. Gas Positive Pressure 328 | 2 Ex. Gas Negative Pressure 329 | 1 Intake Air Solenoid 330 | 0 Muffler Control 331 | 332 | ********** BYTE 27 ********** 333 | 7 ------------------------- 334 | 6 ------------------------- 335 | 5 ------------------------- 336 | 4 ------------------------- 337 | 3 Retard Signal from AT 338 | 2 Fuel Cut Signal from AT 339 | 1 Ban of Torque Down 340 | 0 Request Torque Down VDC 341 | 342 | ********** BYTE 28 ********** 343 | 7 Torque Control Signal #1 344 | 6 Torque Control Signal #2 345 | 5 Torque Permission Signal 346 | 4 EAM signal 347 | 3 AT coop. lock up signal 348 | 2 AT coop. lean burn signal 349 | 1 AT coop. rich spike signal 350 | 0 AET Signal 351 | 352 | ********** BYTE 29 ********** 353 | 7 ------------------------- 354 | 6 ------------------------- 355 | 5 ------------------------- 356 | 4 ------------------------- 357 | 3 ------------------------- 358 | 2 ------------------------- 359 | 1 ------------------------- 360 | 0 ------------------------- 361 | 362 | ********** BYTE 30 ********** 363 | 7 ------------------------- 364 | 6 ------------------------- 365 | 5 ------------------------- 366 | 4 ------------------------- 367 | 3 ------------------------- 368 | 2 ------------------------- 369 | 1 ------------------------- 370 | 0 ------------------------- 371 | 372 | ********** BYTE 31 ********** 373 | 7 ------------------------- 374 | 6 ------------------------- 375 | 5 ------------------------- 376 | 4 ------------------------- 377 | 3 ------------------------- 378 | 2 ------------------------- 379 | 1 ------------------------- 380 | 0 ------------------------- 381 | 382 | ********** BYTE 32 ********** 383 | 7 ------------------------- 384 | 6 ------------------------- 385 | 5 ------------------------- 386 | 4 ------------------------- 387 | 3 ------------------------- 388 | 2 ------------------------- 389 | 1 ------------------------- 390 | 0 ------------------------- 391 | 392 | ********** BYTE 33 ********** 393 | 7 ------------------------- 394 | 6 ------------------------- 395 | 5 ------------------------- 396 | 4 ------------------------- 397 | 3 ------------------------- 398 | 2 ------------------------- 399 | 1 ------------------------- 400 | 0 ------------------------- 401 | 402 | ********** BYTE 34 ********** 403 | 7 ------------------------- 404 | 6 ------------------------- 405 | 5 ------------------------- 406 | 4 ------------------------- 407 | 3 ------------------------- 408 | 2 ------------------------- 409 | 1 ------------------------- 410 | 0 ------------------------- 411 | 412 | ********** BYTE 35 ********** 413 | 7 ------------------------- 414 | 6 ------------------------- 415 | 5 ------------------------- 416 | 4 ------------------------- 417 | 3 ------------------------- 418 | 2 ------------------------- 419 | 1 ------------------------- 420 | 0 ------------------------- 421 | 422 | ********** BYTE 36 ********** 423 | 7 ------------------------- 424 | 6 ------------------------- 425 | 5 ------------------------- 426 | 4 ------------------------- 427 | 3 ------------------------- 428 | 2 ------------------------- 429 | 1 ------------------------- 430 | 0 ------------------------- 431 | 432 | ********** BYTE 37 ********** 433 | 7 ------------------------- 434 | 6 ------------------------- 435 | 5 ------------------------- 436 | 4 ------------------------- 437 | 3 ------------------------- 438 | 2 ------------------------- 439 | 1 ------------------------- 440 | 0 ------------------------- 441 | 442 | ********** BYTE 38 ********** 443 | 7 ------------------------- 444 | 6 ------------------------- 445 | 5 ------------------------- 446 | 4 ------------------------- 447 | 3 ------------------------- 448 | 2 ------------------------- 449 | 1 ------------------------- 450 | 0 ------------------------- 451 | 452 | ********** BYTE 39 ********** 453 | 7 ------------------------- 454 | 6 ------------------------- 455 | 5 Throttle Motor Duty 456 | 4 Throttle Motor Voltage 457 | 3 ------------------------- 458 | 2 ------------------------- 459 | 1 ------------------------- 460 | 0 ------------------------- 461 | 462 | ********** BYTE 40 ********** 463 | 7 ------------------------- 464 | 6 ------------------------- 465 | 5 ------------------------- 466 | 4 ------------------------- 467 | 3 ------------------------- 468 | 2 ------------------------- 469 | 1 ------------------------- 470 | 0 ------------------------- 471 | 472 | ********** BYTE 41 ********** 473 | 7 Sub Throttle Sensor 474 | 6 Main Throttle Sensor 475 | 5 Sub Accelerator Sensor 476 | 4 Main Accelerator Sensor 477 | 3 Brake Booster Pressure 478 | 2 Fuel Pressure (High) 479 | 1 Exhaust Gas Temperature 480 | 0 ------------------------- 481 | 482 | ********** BYTE 42 ********** 483 | 7 Cold Start Injector 484 | 6 SCV Step 485 | 5 Memorized Cruise Speed 486 | 4 ------------------------- 487 | 3 ------------------------- 488 | 2 ------------------------- 489 | 1 ------------------------- 490 | 0 ------------------------- 491 | 492 | ********** BYTE 43 ********** 493 | 7 ------------------------- 494 | 6 ------------------------- 495 | 5 ------------------------- 496 | 4 ------------------------- 497 | 3 ------------------------- 498 | 2 ------------------------- 499 | 1 ------------------------- 500 | 0 ------------------------- 501 | 502 | ********** BYTE 44 ********** 503 | 7 Exhaust VVT Advance Angle Right 504 | 6 Exhaust VVT Advance Angle Left 505 | 5 Exhaust OCV Duty Right 506 | 4 Exhaust OCV Duty Left 507 | 3 Exhaust OCV Current Right 508 | 2 Exhaust OCV Current Left 509 | 1 ------------------------- 510 | 0 ------------------------- 511 | 512 | ********** BYTE 45 ********** 513 | 7 ------------------------- 514 | 6 ETC Motor Relay 515 | 5 ------------------------- 516 | 4 ------------------------- 517 | 3 ------------------------- 518 | 2 ------------------------- 519 | 1 ------------------------- 520 | 0 ------------------------- 521 | 522 | ********** BYTE 46 ********** 523 | 7 Clutch Switch 524 | 6 Stop Light Switch 525 | 5 Set/Coast Switch 526 | 4 Resume/Accelerate Switch 527 | 3 Brake Switch 528 | 2 ------------------------- 529 | 1 Accelerator Switch 530 | 0 ------------------------- 531 | 532 | ********** BYTE 47 ********** 533 | 7 ------------------------- 534 | 6 ------------------------- 535 | 5 ------------------------- 536 | 4 ------------------------- 537 | 3 ------------------------- 538 | 2 ------------------------- 539 | 1 ------------------------- 540 | 0 ------------------------- 541 | 542 | ********** BYTE 48 ********** 543 | 7 ------------------------- 544 | 6 ------------------------- 545 | 5 ------------------------- 546 | 4 ------------------------- 547 | 3 ------------------------- 548 | 2 ------------------------- 549 | 1 ------------------------- 550 | 0 ------------------------- 551 | 552 | ********** BYTE 49 ********** 553 | 7 ------------------------- 554 | 6 ------------------------- 555 | 5 ------------------------- 556 | 4 ------------------------- 557 | 3 ------------------------- 558 | 2 ------------------------- 559 | 1 ------------------------- 560 | 0 ------------------------- 561 | 562 | ********** BYTE 50 ********** 563 | 7 ------------------------- 564 | 6 ------------------------- 565 | 5 ------------------------- 566 | 4 ------------------------- 567 | 3 ------------------------- 568 | 2 ------------------------- 569 | 1 ------------------------- 570 | 0 ------------------------- 571 | 572 | ********** BYTE 51 ********** 573 | 7 ------------------------- 574 | 6 ------------------------- 575 | 5 ------------------------- 576 | 4 ------------------------- 577 | 3 ------------------------- 578 | 2 ------------------------- 579 | 1 ------------------------- 580 | 0 ------------------------- 581 | 582 | ********** BYTE 52 ********** 583 | 7 ------------------------- 584 | 6 ------------------------- 585 | 5 ------------------------- 586 | 4 ------------------------- 587 | 3 ------------------------- 588 | 2 ------------------------- 589 | 1 ------------------------- 590 | 0 ------------------------- 591 | 592 | ********** BYTE 53 ********** 593 | 7 ------------------------- 594 | 6 ------------------------- 595 | 5 ------------------------- 596 | 4 ------------------------- 597 | 3 ------------------------- 598 | 2 ------------------------- 599 | 1 ------------------------- 600 | 0 ------------------------- 601 | 602 | ********** BYTE 54 ********** 603 | 7 ------------------------- 604 | 6 ------------------------- 605 | 5 ------------------------- 606 | 4 ------------------------- 607 | 3 ------------------------- 608 | 2 ------------------------- 609 | 1 ------------------------- 610 | 0 ------------------------- 611 | 612 | ********** BYTE 55 ********** 613 | 7 ------------------------- 614 | 6 ------------------------- 615 | 5 ------------------------- 616 | 4 ------------------------- 617 | 3 ------------------------- 618 | 2 ------------------------- 619 | 1 ------------------------- 620 | 0 ------------------------- 621 | 622 | ********** BYTE 56 ********** 623 | 7 Roughness Monitor Cylinder #1 624 | 6 Roughness Monitor Cylinder #2 625 | 5 Roughness Monitor Cylinder #3 626 | 4 Roughness Monitor Cylinder #4 627 | 3 ------------------------- 628 | 2 ------------------------- 629 | 1 ------------------------- 630 | 0 ------------------------- 631 | 632 | 633 | Parameters are read by providing a 3 byte address for each parameter via command 0xA8 For example use address 0x000008 for Coolant temp 634 | and use addresses 0x00000E and 0x00000F for engine RPM 635 | 636 | Parameters ********************************************************** 637 | 638 | - Engine Load ---------------------------------------------- 639 | 8 bit value 640 | P0x07 = low byte 641 | 642 | Multiply value by 100.0 and divide by 255 to get percent 643 | ------------------------------------------------------------ 644 | - Coolant Temperature -------------------------------------- 645 | 8 bit value 646 | P0x008 = low byte 647 | 648 | 649 | Subtract 40 from value to get Degrees C 650 | ------------------------------------------------------------ 651 | - Air/Fuel Correction #1 ----------------------------------- 652 | 8 bit value 653 | P0x009 = low byte 654 | 655 | Subtract 128 from value and divide by 1.28 to get percent 656 | ------------------------------------------------------------ 657 | - Air/Fuel Learning #1 ------------------------------------- 658 | 8 bit value 659 | P0x00A = low byte 660 | 661 | Subtract 128 from value and divide by 1.28 to get percent 662 | ------------------------------------------------------------ 663 | - Air/Fuel Correction #2 ----------------------------------- 664 | 8 bit value 665 | P0x00B = low byte 666 | 667 | Subtract 128 from value and divide by 1.28 to get percent 668 | ------------------------------------------------------------ 669 | - Air/Fuel Learning #2 ------------------------------------- 670 | 8 bit value 671 | P0x00C = low byte 672 | 673 | Subtract 128 from value and divide by 1.28 to get percent 674 | ------------------------------------------------------------ 675 | - Manifold Absolute Pressure ------------------------------- 676 | 8 bit value 677 | P0x0D = low byte 678 | 679 | Multiply value by 37.0 and divide by 255 to get psig 680 | ------------------------------------------------------------ 681 | - Engine Speed --------------------------------------------- 682 | 16 bit value 683 | P0x0E = high byte 684 | P0x0F = low byte 685 | 686 | Divide value by 4 to get RPM 687 | ------------------------------------------------------------ 688 | - Vehicle Speed -------------------------------------------- 689 | 8 bit value 690 | P0x010 = low byte 691 | 692 | Value is in km/h 693 | ------------------------------------------------------------ 694 | - Ignition Timing ------------------------------------------ 695 | 8 bit balue P0x11 = low byte 696 | 697 | Subtract 128 from value and divide by 2 to get degrees 698 | ------------------------------------------------------------ 699 | - Intake Air Temperature ----------------------------------- 700 | 8 bit value 701 | P0x012 = low byte 702 | 703 | Subtract 40 from value to get Degrees C 704 | ------------------------------------------------------------ 705 | - Mass Air Flow -------------------------------------------- 706 | 16 bit value 707 | P0x13 = high byte 708 | P0x14 = low byte 709 | 710 | Divide value by 100.0 to get grams/s 711 | ------------------------------------------------------------ 712 | - Throttle Opening Angle ----------------------------------- 713 | 8 bit value 714 | P0x15 = low byte 715 | 716 | Multiply value by 100.0 and divide by 255 to get percent 717 | ------------------------------------------------------------ 718 | - Front O2 Sensor #1 --------------------------------------- 719 | 16 bit value 720 | P0x016 = high byte 721 | P0x017 = low byte 722 | 723 | Multiply value by 0.005 to get voltage 724 | ------------------------------------------------------------ 725 | - Rear O2 Sensor ------------------------------------------- 726 | 16 bit value 727 | P0x018 = high byte 728 | P0x019 = low byte 729 | 730 | Multiply value by 0.005 to get voltage 731 | ------------------------------------------------------------ 732 | - Front O2 Sensor #2 --------------------------------------- 733 | 16 bit value 734 | P0x01A = high byte 735 | P0x01B = low byte 736 | 737 | Multiply value by 0.005 to get voltage 738 | ------------------------------------------------------------ 739 | - Battery Voltage ------------------------------------------ 740 | 8 bit value 741 | P0x01C = low byte 742 | 743 | Multiply value by 0.08 to get volts 744 | ------------------------------------------------------------ 745 | - Air Flow Sensor Voltage ---------------------------------- 746 | 8 bit value 747 | P0x01D = low byte 748 | 749 | Multiply value by 0.02 to get volts 750 | ------------------------------------------------------------ 751 | - Throttle Sensor Voltage ---------------------------------- 752 | 8 bit value 753 | P0x01E = low byte 754 | 755 | Multiply value by 0.02 to get volts 756 | ------------------------------------------------------------ 757 | - Differential Pressure Sensor Voltage --------------------- 758 | 8 bit value 759 | P0x01F = low byte 760 | 761 | Multiply value by 0.02 to get Volts 762 | ------------------------------------------------------------ 763 | - Fuel Injection #1 Pulse Width ---------------------------- 764 | 8 bit value 765 | P0x20 = low byte 766 | 767 | Multiply value by 0.256 to get ms 768 | ------------------------------------------------------------ 769 | - Fuel Injection #2 Pulse Width ---------------------------- 770 | 8 bit value 771 | P0x21 = low byte 772 | 773 | Multiply value by 0.256 to get ms 774 | ------------------------------------------------------------ 775 | - Knock Correction ----------------------------------------- 776 | 8 bit value 777 | P0x22 = low byte 778 | 779 | Subtract 128 from value and divide by 2 to get degrees 780 | ------------------------------------------------------------ 781 | - Atmospheric Pressure ------------------------------------- 782 | 8 bit value 783 | P0x023 = low byte 784 | 785 | Multiply value by 37.0 and divide by 255 to get psig 786 | ------------------------------------------------------------ 787 | - Manifold Relative Pressure ------------------------------- 788 | 8 bit value 789 | P0x24 = low byte 790 | 791 | Subtract 128 from value, multiply by 37.0 and divide by 255 to get psig 792 | ------------------------------------------------------------ 793 | - Pressure Differential Sensor ----------------------------- 794 | 8 bit value 795 | P0x25 = low byte 796 | 797 | Subtract 128 from value, multiply by 37.0 and divide by 255 to get psig 798 | ------------------------------------------------------------ 799 | - Fuel Tank Pressure --------------------------------------- 800 | 8 bit value 801 | P0x026 = low byte 802 | 803 | Subtract 128 from value and multiply by 0.0035 to get psig 804 | ------------------------------------------------------------ 805 | - CO Adjustment -------------------------------------------- 806 | 8 bit value 807 | P0x027 = low byte 808 | 809 | Multiply value by 0.02 to get volts 810 | ------------------------------------------------------------ 811 | - Learned Ignition Timing ---------------------------------- 812 | 8 bit value 813 | P0x028 = low byte 814 | 815 | Subtract 128 from value and divide by 2 to get degrees 816 | ------------------------------------------------------------ 817 | - Accelerator Opening Angle -------------------------------- 818 | 8 bit valuev P0x029 = low byte 819 | 820 | Divide value by 2.56 to get percent 821 | ------------------------------------------------------------ 822 | - Fuel Temperature ----------------------------------------- 823 | 8 bit value 824 | P0x02A = low byte 825 | 826 | Subtract 40 from value to get Degrees C 827 | ------------------------------------------------------------ 828 | - Front O2 Heater #1 --------------------------------------- 829 | 8 bit value 830 | P0x02B = low byte 831 | 832 | Multiply value by 10.04 and divide by 256 to get Amps 833 | ------------------------------------------------------------ 834 | - Rear O2 Heater Current ----------------------------------- 835 | 8 bit value 836 | P0x02C = low byte 837 | 838 | Multiply value by 10.04 and divide by 256 to get Amps 839 | ------------------------------------------------------------ 840 | - Front O2 Heater #2 --------------------------------------- 841 | 8 bit value 842 | P0x02D = low byte 843 | 844 | Multiply value by 10.04 and divide by 256 to get Amps 845 | ------------------------------------------------------------ 846 | - Fuel Level ----------------------------------------------- 847 | 8 bit value 848 | P0x02E = low byte 849 | 850 | Multiply value by 0.02 to get volts 851 | ------------------------------------------------------------ 852 | - Primary Wastegate Duty Cycle ----------------------------- 853 | 8 bit value 854 | P0x30 = low byte 855 | 856 | 857 | 858 | Multiply value by 100.0 and divide by 255 to get percent 859 | ------------------------------------------------------------ 860 | - Secondary Wastegate Duty Cycle --------------------------- 861 | 8 bit value 862 | P0x31 = low byte 863 | 864 | Multiply value by 100.0 and divide by 255 to get percent 865 | ------------------------------------------------------------ 866 | - CPC Valve Duty Ratio ------------------------------------- 867 | 8 bit value 868 | P0x032 = low byte 869 | 870 | Divide value by 2.55 to get percent 871 | ------------------------------------------------------------ 872 | - Tumble Valve Position Sensor Right ----------------------- 873 | 8 bit value 874 | P0x033 = low byte 875 | 876 | Multiply value by 0.02 to get volts 877 | ------------------------------------------------------------ 878 | - Tumble Valve Position Sensor Left ------------------------ 879 | 8 bit value 880 | P0x034 = low byte 881 | 882 | Multiply value by 0.02 to get volts 883 | ------------------------------------------------------------ 884 | - Idle Speed Control Valve Duty Ratio ---------------------- 885 | 8 bit value 886 | P0x035 = low byte 887 | 888 | Divide value by 2 to get percent 889 | ------------------------------------------------------------ 890 | - Air/Fuel Lean Correction --------------------------------- 891 | 8 bit value 892 | P0x036 = low byte 893 | 894 | Divide value by 2.55 to get percent 895 | ------------------------------------------------------------ 896 | - Air/Fuel Heater Duty ------------------------------------- 897 | 8 bit value 898 | P0x037 = low byte 899 | 900 | Divide value by 2.55 to get percent 901 | ------------------------------------------------------------ 902 | - Idle Speed Control Valve Step ---------------------------- 903 | 8 bit value 904 | P0x038 = low byte 905 | 906 | Value is in steps 907 | ------------------------------------------------------------ 908 | - Number of Ex. Gas Recirc. Steps -------------------------- 909 | 8 bit value 910 | P0x039 = low byte 911 | 912 | Value is in steps 913 | ------------------------------------------------------------ 914 | - Alternator Duty ------------------------------------------ 915 | 8 bit value 916 | P0x03A = low byte 917 | 918 | Value is in percent 919 | ------------------------------------------------------------ 920 | - Fuel Pump Duty ------------------------------------------- 921 | 8 bit value 922 | P0x03B = low byte 923 | 924 | Divide value by 2.55 to get percent 925 | ------------------------------------------------------------ 926 | - Intake VVT Advance Angle Right --------------------------- 927 | 8 bit value 928 | P0x03C = low byte 929 | 930 | Subtract 50 from value to get degrees 931 | ------------------------------------------------------------ 932 | - Intake VVT Advance Angle Left --------------------------- 933 | 8 bit value 934 | P0x03D = low byte 935 | 936 | Subtract 50 from value to get degrees 937 | ------------------------------------------------------------ 938 | - Intake OCV Duty Right ------------------------------------ 939 | 8 bit value 940 | P0x03E = low byte 941 | 942 | Divide value by 2.55 to get percent 943 | ------------------------------------------------------------ 944 | - Intake OCV Duty Left ------------------------------------- 945 | 8 bit value 946 | P0x03F = low byte 947 | 948 | Divide value by 2.55 to get percent 949 | ------------------------------------------------------------ 950 | - Intake OCV Current Right --------------------------------- 951 | 8 bit value 952 | P0x040 = low byte 953 | 954 | Multiply value by 32 to get mA 955 | ------------------------------------------------------------ 956 | - Intake OCV Current Left ---------------------------------- 957 | 8 bit value 958 | P0x041 = low byte 959 | 960 | Multiply value by 32 to get mA 961 | ------------------------------------------------------------ 962 | - Air/Fuel Sensor #1 Current ------------------------------- 963 | 8 bit value 964 | P0x042 = low byte 965 | 966 | Subtract 128 from value and multiply by .125 to get mA 967 | ------------------------------------------------------------ 968 | - Air/Fuel Sensor #2 Current ------------------------------- 969 | 8 bit value 970 | P0x043 = low byte 971 | 972 | Subtract 128 from value and multiply by .125 to get mA 973 | ------------------------------------------------------------ 974 | - Air/Fuel Sensor #1 Resistance ---------------------------- 975 | 8 bit value 976 | P0x044 = low byte 977 | 978 | Value is in ohms 979 | ------------------------------------------------------------ 980 | - Air/Fuel Sensor #2 Resistance ---------------------------- 981 | 8 bit value 982 | P0x045 = low byte 983 | 984 | Value is in ohms 985 | ------------------------------------------------------------ 986 | - Air/Fuel Sensor #1 --------------------------------------- 987 | 8 bit value 988 | P0x46 = low byte 989 | 990 | Divide value by 128.0 to get Lambda 991 | ------------------------------------------------------------ 992 | - Air/Fuel Sensor #2 --------------------------------------- 993 | 8 bit value 994 | P0x47 = low byte 995 | 996 | Divide value by 128.0 to get Lambda 997 | ------------------------------------------------------------ 998 | - Gear Position -------------------------------------------- 999 | 8 bit value 1000 | P0x04A = low byte 1001 | 1002 | Add 1 to value to get gear 1003 | ------------------------------------------------------------ 1004 | - A/F Sensor #1 Heater Current ----------------------------- 1005 | 8 bit value 1006 | P0x053 = low byte 1007 | 1008 | Divide value by 10 to get Amps 1009 | ------------------------------------------------------------ 1010 | - A/F Sensor #2 Heater Current ----------------------------- 1011 | 8 bit value 1012 | P0x054 = low byte 1013 | 1014 | 1015 | Divide value by 10 to get Amps 1016 | ------------------------------------------------------------ 1017 | - Roughness Monitor Cylinder #1 ---------------------------- 1018 | 8 bit value 1019 | P0x0CE = low byte 1020 | 1021 | Value is in ? 1022 | ------------------------------------------------------------ 1023 | - Roughness Monitor Cylinder #2 ---------------------------- 1024 | 8 bit value 1025 | P0x0CF = low byte 1026 | 1027 | Value is in ? 1028 | ------------------------------------------------------------ 1029 | - Air/Fuel Correction #3 ----------------------------------- 1030 | 8 bit value 1031 | P0x0D0 = low byte 1032 | 1033 | Subtract 128 from value and divide by 1.28 to get percent 1034 | ------------------------------------------------------------ 1035 | - Air/Fuel Learning #3 ------------------------------------- 1036 | 8 bit value 1037 | 1038 | P0x0D1 = low byte 1039 | 1040 | Subtract 128 from value and divide by 1.28 to get percent 1041 | ------------------------------------------------------------ 1042 | - Rear O2 Heater Voltage ----------------------------------- 1043 | 8 bit value 1044 | P0x0D2 = low byte 1045 | 1046 | Multiply value by 0.02 to get volts 1047 | ------------------------------------------------------------ 1048 | - Air/Fuel Adjustment Voltage ------------------------------ 1049 | 8 bit value 1050 | P0x0D3 = low byte 1051 | 1052 | Multiply value by 0.02 to get voltage 1053 | ------------------------------------------------------------ 1054 | - Roughness Monitor Cylinder #3 ---------------------------- 1055 | 8 bit value 1056 | P0x0D8 = low byte 1057 | 1058 | Value is in ? 1059 | ------------------------------------------------------------ 1060 | - Roughness Monitor Cylinder #4 ---------------------------- 1061 | 8 bit value 1062 | P0x0D9 = low byte 1063 | 1064 | Value is in ? 1065 | ------------------------------------------------------------ 1066 | - Throttle Motor Duty -------------------------------------- 1067 | 8 bit value 1068 | P0x0fa = low byte 1069 | 1070 | Subtract 128 from value and divide by 1.28 to get percent 1071 | ------------------------------------------------------------ 1072 | - Throttle Motor Voltage ----------------------------------- 1073 | 8 bit value 1074 | P0x0FB = low byte 1075 | 1076 | Multiply value by 0.08 to get volts 1077 | ------------------------------------------------------------ 1078 | - Sub Throttle Sensor -------------------------------------- 1079 | 8 bit value 1080 | P0x100 = low byte 1081 | 1082 | Multiply value by 0.02 to get volts 1083 | ------------------------------------------------------------ 1084 | - Main Throttle Sensor ------------------------------------- 1085 | 8 bit value 1086 | P0x101 = low byte 1087 | 1088 | Multiply value by 0.02 to get volts 1089 | ------------------------------------------------------------ 1090 | - Sub Accelerator Sensor ----------------------------------- 1091 | 8 bit value 1092 | P0x102 = low byte 1093 | 1094 | Multiply value by 0.02 to get volts 1095 | ------------------------------------------------------------ 1096 | - Main Accelerator Sensor ---------------------------------- 1097 | 8 bit value 1098 | P0x103 = low byte 1099 | 1100 | Multiply value by 0.02 to get volts 1101 | ------------------------------------------------------------ 1102 | - Brake Booster Pressure ----------------------------------- 1103 | 8 bit value 1104 | P0x104 = low byte 1105 | 1106 | Multiply value by 37.0 and divide by 255 to get psig 1107 | ------------------------------------------------------------ 1108 | - Fuel Pressure (High) ------------------------------------- 1109 | 8 bit value 1110 | P0x105 = low byte 1111 | 1112 | Multiply value by 0.04 to get MPa 1113 | ------------------------------------------------------------ 1114 | - Exhaust Gas Temperature ---------------------------------- 1115 | 8 bit value 1116 | P0x106 = low byte 1117 | 1118 | Add 40 to value and multiply by 5 to get Degrees C 1119 | ------------------------------------------------------------ 1120 | - Cold Start Injector -------------------------------------- 1121 | 8 bit value 1122 | P0x108 = low byte 1123 | 1124 | Multiply value by .256 to get ms 1125 | ------------------------------------------------------------ 1126 | - SCV Step ------------------------------------------------- 1127 | 8 bit value 1128 | P0x109 = low byte 1129 | 1130 | Value is in Steps 1131 | ------------------------------------------------------------ 1132 | - Memorised Cruise Speed ----------------------------------- 1133 | 8 bit value 1134 | P0x10a = low byte 1135 | 1136 | Value is in km/h 1137 | ------------------------------------------------------------ 1138 | - Exhaust VVT Advance Angle Right -------------------------- 1139 | 8 bit value 1140 | P0x118 = low byte 1141 | 1142 | Subtract 50 from value to get degrees 1143 | ------------------------------------------------------------ 1144 | - Exhaust VVT Advance Angle Left --------------------------- 1145 | 8 bit value 1146 | P0x119 = low byte 1147 | 1148 | Subtract 50 from value to get degrees 1149 | ------------------------------------------------------------ 1150 | - Exhaust OCV Duty Right ----------------------------------- 1151 | 8 bit value 1152 | P0x11A = low byte 1153 | 1154 | Divide value by 2.55 to get percent 1155 | ------------------------------------------------------------ 1156 | - Exhaust OCV Duty Left ------------------------------------ 1157 | 8 bit value 1158 | P0x11B = low byte 1159 | 1160 | Divide value by 2.55 to get percent 1161 | ------------------------------------------------------------ 1162 | - Exhaust OCV Current Right -------------------------------- 1163 | 8 bit value 1164 | P0x11C = low byte 1165 | 1166 | Multiply value by 32 to get mA 1167 | ------------------------------------------------------------ 1168 | - Exhaust OCV Current Left --------------------------------- 1169 | 8 bit value 1170 | P0x11D = low byte 1171 | 1172 | Multiply value by 32 to get mA 1173 | ------------------------------------------------------------ 1174 | 1175 | 1176 | 1177 | Switches are read in the same way a parameter is read except that it will 1178 | return up to 1179 | 8 individual ON/OFF flags in the individual bits of the return byte 1180 | 1181 | Switches ************************************************************** 1182 | 1183 | Switch P0x061 1184 | 7 ----------------------- 1185 | 6 AT Vehicle ID 1186 | 5 Test Mode Connector 1187 | 4 Read Memory Connector 1188 | 3 ----------------------- 1189 | 2 ----------------------- 1190 | 1 ----------------------- 1191 | 0 ----------------------- 1192 | 1193 | Switch P0x062 1194 | 7 Neutral Position Switch 1195 | 6 Idle Switch 1196 | 5 ----------------------- 1197 | 4 Intercooler AutoWash Switch 1198 | 3 Ignition Switch 1199 | 2 Power Steering Switch 1200 | 1 Air Conditioning Switch 1201 | 0 ----------------------- 1202 | 1203 | Switch P0x063 1204 | 7 Handle Switch 1205 | 6 Starter Switch 1206 | 5 Front O2 Rich Signal 1207 | 4 Rear O2 Rich Signal 1208 | 3 Front O2 #2 Rich Signal 1209 | 2 Knock Signal 1 1210 | 1 Knock Signal 2 1211 | 0 Electrical Load Signal 1212 | 1213 | Switch P0x064 1214 | 7 Crank Position Sensor 1215 | 6 Cam Position Sensor 1216 | 5 Defogger Switch 1217 | 4 Blower Switch 1218 | 3 Interior Light Switch 1219 | 2 Wiper Switch 1220 | 1 Air-Con Lock Signal 1221 | 0 Air-Con Mid Pressure Switch 1222 | 1223 | Switch P0x065 1224 | 7 Air-Con Compressor Signal 1225 | 6 Radiator Fan Relay #3 1226 | 5 Radiator Fan Relay #1 1227 | 4 Radiator Fan Relay #2 1228 | 3 Fuel Pump Relay 1229 | 2 Intercooler Auto-Wash Relay 1230 | 1 CPC Solenoid Valve 1231 | 0 Blow-By Leak Connector 1232 | 1233 | Switch P0x066 1234 | 7 PCV Solenoid Valve 1235 | 6 TGV Output 1236 | 5 TGV Drive 1237 | 4 Variable Intake Air Solenoid 1238 | 3 Pressure Sources Change 1239 | 2 Vent Solenoid Valve 1240 | 1 P/S Solenoid Valve 1241 | 0 Assist Air Solenoid Valve 1242 | 1243 | Switch P0x067 1244 | 7 Tank Sensor Control Valve 1245 | 6 Relief Valve Solenoid 1 1246 | 5 Relief Valve Solenoid 2 1247 | 4 TCS Relief Valve Solenoid 1248 | 3 Ex. Gas Positive Pressure 1249 | 2 Ex. Gas Negative Pressure 1250 | 1 Intake Air Solenoid 1251 | 0 Muffler Control 1252 | 1253 | Switch P0x068 1254 | 7 ----------------------- 1255 | 6 ----------------------- 1256 | 5 ----------------------- 1257 | 4 ----------------------- 1258 | 3 Retard Signal from AT 1259 | 2 Fuel Cut Signal from AT 1260 | 1 Ban of Torque Down 1261 | 0 Request Torque Down VDC 1262 | 1263 | Switch P0x069 1264 | 7 Torque Control Signal #1 1265 | 6 Torque Control Signal #2 1266 | 5 Torque Permission Signal 1267 | 4 EAM Signal 1268 | 3 AT coop. lock up signal 1269 | 2 AT coop. lean burn signal 1270 | 1 AT coop. rich spike signal 1271 | 0 AET Signal 1272 | 1273 | Switch P0x120 1274 | 7 ----------------------- 1275 | 6 ETC Motor Relay 1276 | 5 ----------------------- 1277 | 4 ----------------------- 1278 | 3 ----------------------- 1279 | 2 ----------------------- 1280 | 1 ----------------------- 1281 | 0 ----------------------- 1282 | 1283 | Switch P0x121 1284 | 7 Clutch Switch 1285 | 6 Stop Light Switch 1286 | 5 Set/Coast Switch 1287 | 4 Rsume/Accelerate Switch 1288 | 3 Brake Switch 1289 | 2 ----------------------- 1290 | 1 Accelerator Switch 1291 | 0 ----------------------- 1292 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | *) More NUnit tests and test code improvements. 4 | Good to show usability, find bugs and add/improve error checking 5 | especially for corner cases. 6 | 7 | 8 | *) Override ToString() for debugging. 9 | Also enhance and test Equals, GetHashCode methods, 10 | might be useful in some cases. 11 | 12 | 13 | *) Add more init data functionality. 14 | Should provide system type strings like "2.0L DOHC" as well as 15 | easy access to capability flag bits. 16 | I already did something similar, just need to get it integrated here. 17 | Not sure yet whether to add members in Ssm2InitResponse packet class 18 | or create an additional non-packet class. 19 | 20 | 21 | *) Another two subclasses to implement 22 | Write-Block-Request (B0) and Write-Block-Response (F0). 23 | Anyone needs these at all? Won't be much work though. 24 | Are those used for flashing (firmware update)? 25 | Both command bytes are already included in Ssm2Command enumeration. 26 | 27 | 28 | *) Conditional compilation instructions to only include needed functionality. 29 | Might be useful to reduce assembly size for limited devices (PocketPC). 30 | E.g. only include necessary types for sampling (Init, Read-Addresses) 31 | since most applications on small devices won't do stuff like 32 | maintenance operations. 33 | 34 | -------------------------------------------------------------------------------- /TestLibSSM2/TestLibSSM2.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {63A997C2-08F6-43F9-B089-5894D2833C28} 9 | Library 10 | Subaru.SSM2 11 | TestLibSSM2 12 | v3.5 13 | 1.0 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug 20 | DEBUG 21 | prompt 22 | 4 23 | 24 | 25 | none 26 | false 27 | bin\Release 28 | prompt 29 | 4 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | {60C26865-ACC4-450B-9030-3978314C7DDA} 50 | LibSSM2 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /TestLibSSM2/TestSsm2InitRequest.cs: -------------------------------------------------------------------------------- 1 | // TestSsm2InitRequest.cs: Test SSM2 init request class. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using NUnit.Framework; 23 | 24 | namespace Subaru.SSM2 25 | { 26 | 27 | [TestFixture()] 28 | public class TestSsm2InitRequest 29 | { 30 | /// 31 | /// Typical engine control unit init request. 32 | /// 33 | static readonly byte[] EcuInit1 = { 0x80, 0x10, 0xF0, 0x01, 0xBF, 0x40 }; 34 | 35 | [Test()] 36 | public void CreateByConstructor () 37 | { 38 | // Only 2 standard properties/arguments to specify for this type of packet. 39 | Ssm2InitRequest p = new Ssm2InitRequest (Ssm2Device.Engine10, Ssm2Device.DiagnosticToolF0); 40 | 41 | AssertProperties1 (p); 42 | } 43 | 44 | [Test()] 45 | public void CreateByProperties () 46 | { 47 | // Ssm2InitRequest p = new Ssm2InitRequest (); 48 | // p.Destination = Ssm2Device.Engine10; 49 | // p.Source = Ssm2Device.DiagnosticToolF0; 50 | 51 | // same effect, using object initializer syntax: 52 | Ssm2InitRequest p = new Ssm2InitRequest { Destination = Ssm2Device.Engine10, Source = Ssm2Device.DiagnosticToolF0 }; 53 | // Important: packet is still invalid at this point! 54 | 55 | // don't depend on Size yet even though it is correct for this type 56 | // Assert.AreEqual (packetData.Length, p.Size, "Size"); 57 | // No checksum yet so check will fail. 58 | Assert.AreEqual (false, p.Check (), "Check()"); 59 | 60 | // Important: as with default constructor 61 | // the object does not know when all properties have been set. 62 | // This call will calculate the checksum, making packet complete. 63 | p.Finish (); 64 | // packet is now complete 65 | 66 | AssertProperties1 (p); 67 | } 68 | 69 | [Test()] 70 | public void NewFromBytes () 71 | { 72 | byte[] packetData = EcuInit1; 73 | // best for parsing as it does not allocate anything 74 | Ssm2InitRequest p = (Ssm2InitRequest)Ssm2Packet.NewFromBytes (packetData); 75 | // Same static method can also be accessed like this: 76 | // Ssm2InitRequest.NewFromBytes (...) 77 | 78 | AssertProperties1 (p); 79 | } 80 | 81 | [Test()] 82 | public void FromBytes () 83 | { 84 | byte[] packetData = EcuInit1; 85 | // inefficient for parsing, since constructor allocates a buffer 86 | Ssm2InitRequest p = new Ssm2InitRequest (); 87 | // take given buffer, discarding previous implicit buffer 88 | p.FromBytes (packetData); 89 | 90 | AssertProperties1 (p); 91 | } 92 | 93 | [Test()] 94 | public void NewFromBytesBase () 95 | { 96 | // same results as casting to specific type (Ssm2InitRequest) 97 | // sufficient to use base type here since this packet type has no specific data 98 | var p = Ssm2InitRequest.NewFromBytes (EcuInit1); 99 | // object reference gets type Ssm2Packet 100 | 101 | AssertProperties1 (p); 102 | } 103 | 104 | 105 | static void AssertProperties1 (Ssm2Packet p) 106 | { 107 | byte[] expectedPacketData = EcuInit1; 108 | 109 | Assert.IsInstanceOfType (typeof(Ssm2InitRequest), p, "type"); 110 | Assert.IsInstanceOfType (typeof(Ssm2Packet), p, "base type"); 111 | 112 | Assert.AreEqual (expectedPacketData.Length, p.Size, "Size"); 113 | Assert.AreEqual (true, p.Check (), "Check()"); 114 | 115 | Assert.AreEqual (Ssm2Device.Engine10, p.Destination, "Destination"); 116 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Source, "Source"); 117 | Assert.AreEqual (Ssm2Command.InitRequestBF, p.Command, "Command"); 118 | 119 | byte[] bytes = p.ToBytesCopy (); 120 | for (int i = 0; i < expectedPacketData.Length; i++) { 121 | Assert.AreEqual (expectedPacketData[i], bytes[i], "bytes[]"); 122 | } 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /TestLibSSM2/TestSsm2InitResponse.cs: -------------------------------------------------------------------------------- 1 | // TestSsm2InitResponse.cs: Test SSM2 init response class. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | using NUnit.Framework; 25 | using Subaru.SSM2; 26 | 27 | namespace Subaru.SSM2 28 | { 29 | 30 | [TestFixture()] 31 | public class TestSsm2InitResponse 32 | { 33 | /// 34 | /// Sample ECU init response from engine to diagnostic tool. 35 | /// Taken from documentation file SSM2_Protocol.txt. 36 | /// Contains 48 capability bytes. 37 | /// 38 | static readonly byte[] TestPacket1 = { 0x80, 0xf0, 0x10, 0x39, 0xff, 0xa2, 0x10, 0xf, 0x1b, 0x14, 39 | 0x40, 0x5, 0x5, 0x73, 0xfa, 0xeb, 0x80, 0x2b, 0xc1, 0x2, 40 | 0xaa, 0x0, 0x10, 0x0, 0x60, 0xce, 0x54, 0xf8, 0xb0, 0x60, 41 | 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xdc, 0x0, 42 | 0x0, 0x55, 0x10, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 43 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 44 | 0x0, 0x1f }; 45 | 46 | // parts for verification 47 | static readonly byte[] SSMID1 = { 0xa2, 0x10, 0xf }; 48 | static readonly byte[] ROMID1 = { 0x1b, 0x14, 0x40, 0x5, 0x5 }; 49 | static readonly byte[] Capabilities1 = { 0x73, 0xfa, 0xeb, 0x80, 0x2b, 0xc1, 0x2, 0xaa, 0x0, 0x10, 50 | 0x0, 0x60, 0xce, 0x54, 0xf8, 0xb0, 0x60, 0x0, 0x0, 0xe0, 51 | 0x0, 0x0, 0x0, 0x0, 0x0, 0xdc, 0x0, 0x0, 0x55, 0x10, 52 | 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 53 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; 54 | 55 | 56 | [Test()] 57 | public void NewFromBytes1 () 58 | { 59 | byte[] packetData = TestPacket1; 60 | var p = (Ssm2InitResponse)Ssm2ReadAddressesRequest.NewFromBytes (packetData); 61 | 62 | Assert.IsInstanceOfType (typeof(Ssm2InitResponse), p, "type"); 63 | Assert.IsInstanceOfType (typeof(Ssm2Packet), p, "base type"); 64 | 65 | AssertKnownProperties1 (p); 66 | AssertContent (p, SSMID1, ROMID1, Capabilities1); 67 | } 68 | 69 | [Test()] 70 | public void Parse1 () 71 | { 72 | byte[] packetData = TestPacket1; 73 | var p = new Ssm2InitResponse (); 74 | p.FromBytes (packetData); 75 | 76 | AssertKnownProperties1 (p); 77 | AssertContent (p, SSMID1, ROMID1, Capabilities1); 78 | } 79 | 80 | [Test()] 81 | public void Construct1 () 82 | { 83 | var p = new Ssm2InitResponse (Ssm2Device.DiagnosticToolF0, Ssm2Device.Engine10, SSMID1, ROMID1, Capabilities1); 84 | 85 | AssertKnownProperties1 (p); 86 | AssertContent (p, SSMID1, ROMID1, Capabilities1); 87 | } 88 | 89 | 90 | #region SetSsmID 91 | 92 | [Test(), ExpectedException(typeof(ArgumentNullException))] 93 | public void SetSsmIDNull () 94 | { 95 | var p = new Ssm2InitResponse (); 96 | p.SetSsmID (null); 97 | } 98 | 99 | [Test(), ExpectedException(typeof(ArgumentOutOfRangeException))] 100 | public void SetSsmID2 () 101 | { 102 | var p = new Ssm2InitResponse (); 103 | p.SetSsmID (new byte[2]); 104 | } 105 | 106 | [Test(), ExpectedException(typeof(ArgumentOutOfRangeException))] 107 | public void SetSsmID4 () 108 | { 109 | var p = new Ssm2InitResponse (); 110 | p.SetSsmID (new byte[4]); 111 | } 112 | 113 | [Test(), ExpectedException(typeof(ArgumentOutOfRangeException))] 114 | public void SetSsmID3 () 115 | { 116 | var p = new Ssm2InitResponse (); 117 | p.SetSsmID (new List (3).ToArray ()); 118 | } 119 | 120 | #endregion SetSsmID 121 | 122 | #region SetRomID 123 | 124 | [Test(), ExpectedException(typeof(ArgumentNullException))] 125 | public void SetRomIDNull () 126 | { 127 | var p = new Ssm2InitResponse (); 128 | p.SetRomID (null); 129 | } 130 | 131 | [Test(), ExpectedException(typeof(ArgumentOutOfRangeException))] 132 | public void SetRomID2 () 133 | { 134 | var p = new Ssm2InitResponse (); 135 | p.SetRomID (new byte[2]); 136 | } 137 | 138 | [Test(), ExpectedException(typeof(ArgumentOutOfRangeException))] 139 | public void SetRomID6 () 140 | { 141 | var p = new Ssm2InitResponse (); 142 | p.SetRomID (new byte[6]); 143 | } 144 | 145 | #endregion SetRomID 146 | 147 | #region SetCapabilities 148 | 149 | [Test(), ExpectedException(typeof(ArgumentNullException))] 150 | public void SetCapabilitiesNull () 151 | { 152 | var p = new Ssm2InitResponse (); 153 | p.SetCapabilities (null); 154 | } 155 | 156 | // TODO Realistic capability bytes minimum, currently no exception 157 | // [Test(), ExpectedException(typeof(ArgumentOutOfRangeException))] 158 | // public void SetCapabilities0 () 159 | // { 160 | // var p = new Ssm2InitResponse (); 161 | // p.SetCapabilities (new byte[0]); 162 | // } 163 | 164 | [Test(), ExpectedException(typeof(ArgumentOutOfRangeException))] 165 | public void SetCapabilities247 () 166 | { 167 | var p = new Ssm2InitResponse (); 168 | // MaxCapabilities length to fit in a packet is 246 169 | p.SetCapabilities (new byte[247]); 170 | } 171 | 172 | #endregion SetCapabilities 173 | 174 | 175 | static void AssertKnownProperties1 (Ssm2InitResponse p) 176 | { 177 | byte[] bytes = p.ToBytesCopy (); 178 | 179 | Assert.AreEqual (bytes.Length, p.Size, "Size"); 180 | 181 | Assert.AreEqual (true, p.Check (), "Check()"); 182 | Assert.AreEqual (0x1f, p.ChecksumCalculated, "ChecksumCalculated"); 183 | 184 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Destination, "Destination"); 185 | Assert.AreEqual (Ssm2Device.Engine10, p.Source, "Source"); 186 | } 187 | 188 | static void AssertContent (Ssm2InitResponse packet, byte[] ssmidExpected, byte[] romidExpected, byte[] capabilitesExpected) 189 | { 190 | Assert.AreEqual (true, packet.Check (), "Check()"); 191 | Assert.AreEqual (Ssm2Command.InitResponseFF, packet.Command, "Command"); 192 | 193 | byte[] ssmID = packet.GetSsmID (); 194 | Assert.AreEqual (3, ssmID.Length, "ssmID.Length"); 195 | for (int i = 0; i < ssmID.Length; i++) { 196 | Assert.AreEqual (ssmidExpected[i], ssmID[i], "ssmID"); 197 | } 198 | 199 | // array implements IList 200 | IList ssmIDlist = packet.GetSsmID (); 201 | for (int i = 0; i < ssmIDlist.Count; i++) { 202 | Assert.AreEqual (ssmidExpected[i], ssmIDlist[i], "ssmID IList"); 203 | } 204 | 205 | byte[] romID = packet.GetRomID (); 206 | Assert.AreEqual (5, romID.Length, "romID.Length"); 207 | for (int i = 0; i < romID.Length; i++) { 208 | Assert.AreEqual (romidExpected[i], romID[i], "romID"); 209 | } 210 | 211 | Assert.AreEqual (capabilitesExpected.Length, packet.CapabilitiesLength, "CapabilitiesLength"); 212 | byte[] capabilities = packet.GetCapabilities (); 213 | Assert.AreEqual (capabilitesExpected.Length, capabilities.Length, "capabilities.Length"); 214 | for (int i = 0; i < capabilities.Length; i++) { 215 | Assert.AreEqual (capabilitesExpected[i], capabilities[i], "capabilities"); 216 | } 217 | } 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /TestLibSSM2/TestSsm2Packet.cs: -------------------------------------------------------------------------------- 1 | // TestSsm2Packet.cs: Test SSM2 packet base class. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using NUnit.Framework; 23 | using System; 24 | 25 | namespace Subaru.SSM2 26 | { 27 | 28 | [TestFixture()] 29 | public class TestSsm2Packet 30 | { 31 | 32 | [Test()] 33 | public void EmptyPacketSpecifyingBuffer () 34 | { 35 | byte[] buffer = new byte[Ssm2Packet.PacketSizeMax]; 36 | 37 | // Constructor for initializing packet object by 38 | // providing own (empty) buffer 39 | 40 | // For parsing existing content use instance method .FromBytes (buffer) or 41 | // static method Ssm2Packet.NewFromBytes (buffer) instead! 42 | 43 | Ssm2Packet p = new Ssm2Packet (buffer); 44 | 45 | // packet buffer mostly contains zeroes 46 | // undefined, don't check: 47 | // Size, CheckSum, etc. 48 | 49 | //Assert.AreEqual (0, p.Size, "Size"); 50 | 51 | Assert.AreEqual ((Ssm2Command)0, p.Command, "Command"); 52 | 53 | // Assert.AreEqual (0, p.ChecksumCalculated, "ChecksumCalculated"); 54 | Assert.AreEqual (false, p.Check (), "Check"); 55 | 56 | // not useful, just demonstrating that packet is invalid 57 | // byte[] buf = p.ToBytesCopy (); 58 | //Assert.AreEqual (0, buf.Length, "buf.Length"); 59 | } 60 | 61 | [Test()] 62 | public void DefaultPacket () 63 | { 64 | Ssm2Packet p = new Ssm2Packet (); 65 | 66 | Assert.AreEqual (false, p.Check (), "Check"); 67 | 68 | // Following tests are very implementation specific 69 | // and rather for debugging purposes! 70 | // Real code should not depend on most packet properties 71 | // except Check(), Capacity, Size. 72 | 73 | // packet is almost empty since no properties haven't been set yet 74 | Assert.AreEqual (Ssm2Packet.PacketSizeMin, p.Size, "Size"); 75 | // only 1st byte is set to 128, all other bytes are 0, 76 | // therefore checksum is 128, too. 77 | Assert.AreEqual (128, p.ChecksumCalculated, "ChecksumCalculated"); 78 | 79 | // not useful, just demonstrating that packet is invalid 80 | byte[] buf = p.ToBytesCopy (); 81 | 82 | // generic packet type has minimum size 83 | Assert.AreEqual (Ssm2Packet.PacketSizeMin, buf.Length, "buf.Length"); 84 | } 85 | 86 | [Test()] 87 | public void EqualsDefaultPacket () 88 | { 89 | Ssm2Packet p1, p2; 90 | p1 = new Ssm2Packet (); 91 | p2 = new Ssm2Packet (); 92 | 93 | Assert.AreEqual (true, p1.Equals (p2), "Equals1"); 94 | Assert.AreEqual (true, p1.Equals ((object)p2), "Equals2"); 95 | } 96 | 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /TestLibSSM2/TestSsm2ReadAddressesRequest.cs: -------------------------------------------------------------------------------- 1 | // TestSsm2ReadAddressesRequest.cs: Test SSM2 read addresses request class. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | using NUnit.Framework; 25 | using Subaru.SSM2; 26 | 27 | namespace Subaru.SSM2 28 | { 29 | 30 | [TestFixture()] 31 | public class TestSsm2ReadAddressesRequest 32 | { 33 | readonly byte[] TestPacket1 = { 0x80, 0x10, 0xf0, 0x5, 0xa8, 0x0, 0x12, 0x34, 0x56, 0xc9 }; 34 | readonly byte[] TestPacket2 = { 0x80, 0x10, 0xf0, 0x8, 0xa8, 0x0, 0x12, 0x34, 0x56, 0x0, 35 | 0x0, 0x1c, 0xe8 }; 36 | 37 | [Test()] 38 | public void ConstructorComplete1 () 39 | { 40 | // Create a ReadAddressesRequest, requesting one address. 41 | 42 | // This constructor takes all needed information, 43 | // allocates optimal buffer size and constructs a complete packet. 44 | Ssm2ReadAddressesRequest p = new Ssm2ReadAddressesRequest ( 45 | Ssm2Device.Engine10, 46 | Ssm2Device.DiagnosticToolF0, 47 | new[] { 0x123456 } 48 | ); 49 | 50 | // Predetermined packet bytes to compare with. 51 | byte[] expected = TestPacket1; 52 | 53 | // check standard properties 54 | Assert.AreEqual (expected.Length, p.Size, "Size"); 55 | Assert.AreEqual (true, p.Check (), "Check()"); 56 | Assert.AreEqual (Ssm2Device.Engine10, p.Destination, "Destination"); 57 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Source, "Source"); 58 | Assert.AreEqual (Ssm2Command.ReadAddressesRequestA8, p.Command, "Command"); 59 | 60 | // check packet type specifics 61 | IList addrList = p.Addresses; 62 | Assert.AreEqual (1, addrList.Count, "addrList.Count"); 63 | Assert.AreEqual (1, p.AddressesCount, "AddressesCount"); 64 | Assert.AreEqual (0x123456, addrList[0], "adr[0]"); 65 | 66 | // take raw packet bytes 67 | byte[] buffer = p.ToBytesCopy (); 68 | 69 | // compare raw packet bytes 70 | for (int i = 0; i < expected.Length; i++) { 71 | Assert.AreEqual (expected[i], buffer[i], "buffer[" + i.ToString () + "]"); 72 | } 73 | } 74 | 75 | [Test()] 76 | public void Parse1 () 77 | { 78 | byte[] expected = TestPacket1; 79 | 80 | // Static method NewFromBytes () analyzes packet type, 81 | // and returns a specific packet object. 82 | // Based on given data in this case we know upfront, 83 | // it'll be an read-addresses-request. 84 | Ssm2ReadAddressesRequest p; 85 | p = (Ssm2ReadAddressesRequest) Ssm2Packet.NewFromBytes (expected); 86 | 87 | // check standard properties 88 | Assert.AreEqual (expected.Length, p.Size, "Size"); 89 | Assert.AreEqual (true, p.Check (), "Check()"); 90 | Assert.AreEqual (Ssm2Device.Engine10, p.Destination, "Destination"); 91 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Source, "Source"); 92 | Assert.AreEqual (Ssm2Command.ReadAddressesRequestA8, p.Command, "Command"); 93 | 94 | // check packet type specifics 95 | IList addresses = p.Addresses; 96 | Assert.AreEqual (1, addresses.Count, "addrList.Count"); 97 | Assert.AreEqual (1, p.AddressesCount, "AddressesCount"); 98 | Assert.AreEqual (0x123456, addresses[0], "adr[0]"); 99 | } 100 | 101 | [Test()] 102 | public void Parse2 () 103 | { 104 | byte[] packetData = TestPacket2; 105 | Ssm2ReadAddressesRequest p = new Ssm2ReadAddressesRequest (); 106 | p.FromBytes (packetData); 107 | 108 | Assert.AreEqual (packetData.Length, p.Size, "Size"); 109 | Assert.AreEqual (true, p.Check (), "Check()"); 110 | 111 | Assert.AreEqual (Ssm2Device.Engine10, p.Destination, "Destination"); 112 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Source, "Source"); 113 | Assert.AreEqual (Ssm2Command.ReadAddressesRequestA8, p.Command, "Command"); 114 | 115 | IList addresses = p.Addresses; 116 | Assert.AreEqual (2, addresses.Count, "addrList.Count"); 117 | Assert.AreEqual (2, p.AddressesCount, "AddressesCount"); 118 | Assert.AreEqual (0x123456, addresses[0], "adr[0]"); 119 | Assert.AreEqual (0x1c, addresses[1], "adr[1]"); 120 | } 121 | 122 | // MaxAddressesPerPacket allowed range: 1 - 84 123 | 124 | [Test(), ExpectedException(typeof(ArgumentOutOfRangeException))] 125 | public void StaticMaxAddressesPerPacket1 () 126 | { 127 | Ssm2ReadAddressesRequest.MaxAddressesPerPacket = 0; 128 | } 129 | 130 | [Test(), ExpectedException(typeof(ArgumentOutOfRangeException))] 131 | public void StaticMaxAddressesPerPacket2 () 132 | { 133 | Ssm2ReadAddressesRequest.MaxAddressesPerPacket = 85; 134 | } 135 | 136 | [Test(), ExpectedException(typeof(InvalidOperationException))] 137 | public void NotAllPropertiesSet1 () 138 | { 139 | Ssm2ReadAddressesRequest p = new Ssm2ReadAddressesRequest (); 140 | p.Source = Ssm2Device.DiagnosticToolF0; 141 | p.Addresses = new int[] { 0 }; 142 | p.Finish (); 143 | } 144 | 145 | [Test(), ExpectedException(typeof(InvalidOperationException))] 146 | public void NotAllPropertiesSet2 () 147 | { 148 | Ssm2ReadAddressesRequest p = new Ssm2ReadAddressesRequest (); 149 | p.Destination = Ssm2Device.Engine10; 150 | p.Addresses = new int[] { 0 }; 151 | p.Finish (); 152 | } 153 | 154 | [Test(), ExpectedException(typeof(InvalidOperationException))] 155 | public void NotAllPropertiesSet3 () 156 | { 157 | Ssm2ReadAddressesRequest p = new Ssm2ReadAddressesRequest (); 158 | p.Destination = Ssm2Device.Engine10; 159 | p.Source = Ssm2Device.DiagnosticToolF0; 160 | p.Finish (); 161 | } 162 | 163 | [Test()] 164 | public void ConstructByPropertiesAndModify1 () 165 | { 166 | byte[] packetData = TestPacket1; 167 | 168 | // will allocate full buffer since number of addresses is unknown 169 | Ssm2ReadAddressesRequest p = new Ssm2ReadAddressesRequest (); 170 | 171 | p.Source = Ssm2Device.DiagnosticToolF0; 172 | p.Destination = Ssm2Device.Engine10; 173 | p.Addresses = new int[] { 0x123456 }; 174 | 175 | // should be ok after setting Data 176 | Assert.AreEqual (packetData.Length, p.Size, "Size before Construct"); 177 | 178 | // necessary to create checksum, making packet complete 179 | p.Finish (); 180 | 181 | 182 | byte[] actual = p.ToBytesCopy (); 183 | for (int i = 0; i < packetData.Length; i++) { 184 | Assert.AreEqual (packetData[i], actual[i], "actual[" + i.ToString () + "]"); 185 | } 186 | 187 | Assert.AreEqual (packetData.Length, p.Size, "Size"); 188 | Assert.AreEqual (true, p.Check (), "Check"); 189 | 190 | Assert.AreEqual (Ssm2Device.Engine10, p.Destination, "Destination"); 191 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Source, "Source"); 192 | Assert.AreEqual (Ssm2Command.ReadAddressesRequestA8, p.Command, "Command"); 193 | 194 | IList addresses = p.Addresses; 195 | Assert.AreEqual (1, addresses.Count, "addrList.Count"); 196 | Assert.AreEqual (1, p.AddressesCount, "AddressesCount"); 197 | Assert.AreEqual (0x123456, addresses[0], "adr[0]"); 198 | 199 | // change properties that don't affect packet length 200 | p.Source = Ssm2Device.Engine10; 201 | p.Destination = Ssm2Device.DiagnosticToolF0; 202 | p.Addresses = new[] { 1, 2, 3 }; 203 | p.Finish (); 204 | 205 | Assert.AreEqual (true, p.Check (), "Check2"); 206 | 207 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Destination, "Destination2"); 208 | Assert.AreEqual (Ssm2Device.Engine10, p.Source, "Source2"); 209 | Assert.AreEqual (Ssm2Command.ReadAddressesRequestA8, p.Command, "Command2"); 210 | Assert.AreEqual (3, p.AddressesCount, "AddressesCount2"); 211 | addresses = p.Addresses; 212 | Assert.AreEqual (3, addresses.Count, "addrList.Count2"); 213 | Assert.AreEqual (1, addresses[0], "adr2[0]"); 214 | Assert.AreEqual (2, addresses[1], "adr2[1]"); 215 | Assert.AreEqual (3, addresses[2], "adr2[2]"); 216 | } 217 | 218 | 219 | 220 | [Test(), ExpectedException(typeof(ArgumentOutOfRangeException))] 221 | public void AddressesCountOutOfRange0 () 222 | { 223 | // this constructor will allocate optimal buffer and return a complete packet 224 | new Ssm2ReadAddressesRequest (Ssm2Device.Engine10, Ssm2Device.DiagnosticToolF0, new int[] { }); 225 | // no need to call Construct() with above constructor 226 | } 227 | 228 | [Test(), ExpectedException(typeof(ArgumentOutOfRangeException))] 229 | public void AddressesCountOutOfRange1 () 230 | { 231 | Ssm2ReadAddressesRequest.MaxAddressesPerPacket = 5; 232 | new Ssm2ReadAddressesRequest (Ssm2Device.Engine10, Ssm2Device.DiagnosticToolF0, new int[] { 1, 2, 3, 4, 5, 6 }); 233 | } 234 | 235 | [Test()] 236 | public void IncreaseAddressesCount1 () 237 | { 238 | Ssm2ReadAddressesRequest.MaxAddressesPerPacket = 30; 239 | var p = new Ssm2ReadAddressesRequest (Ssm2Device.Engine10, Ssm2Device.DiagnosticToolF0, new int[] { 1, 2, 3, 4, 5, 6 }); 240 | 241 | // modify 242 | p.Addresses = new int[] { 1, 2, 3, 4, 5, 6, 7 }; 243 | p.Finish (); 244 | 245 | // Assert.AreEqual (packetData.Length, p.Size, "Size"); 246 | Assert.AreEqual (true, p.Check (), "Check()"); 247 | 248 | Assert.AreEqual (Ssm2Device.Engine10, p.Destination, "Destination"); 249 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Source, "Source"); 250 | Assert.AreEqual (Ssm2Command.ReadAddressesRequestA8, p.Command, "Command"); 251 | 252 | IList addresses = p.Addresses; 253 | Assert.AreEqual (7, addresses.Count, "addrList.Count"); 254 | Assert.AreEqual (7, p.AddressesCount, "AddressesCount"); 255 | // Assert.AreEqual (0x123456, addresses[0], "adr[0]"); 256 | 257 | } 258 | 259 | [Test(), ExpectedException(typeof(ArgumentOutOfRangeException))] 260 | public void MaxAddressesPerPacket0 () 261 | { 262 | // at least one address is required, max value cannot be < 1 263 | Ssm2ReadAddressesRequest.MaxAddressesPerPacket = 0; 264 | } 265 | 266 | [Test(), ExpectedException(typeof(ArgumentOutOfRangeException))] 267 | public void MaxAddressesPerPacketMax () 268 | { 269 | // theoretical packet maximum is 84 270 | // in practice it is usually lower, depends on car 271 | // Modern car ECUs support up to 82 addresses per packet. 272 | Ssm2ReadAddressesRequest.MaxAddressesPerPacket = 85; 273 | } 274 | 275 | [Test()] 276 | public void NewFromBytes1 () 277 | { 278 | byte[] packetData = TestPacket1; 279 | // Static method NewFromBytes () analyzes packet type, 280 | // and returns a specific packet object. 281 | // Based on given data in this case we know upfront, 282 | // it'll be an read-addresses-request. 283 | var p = Ssm2ReadAddressesRequest.NewFromBytes (packetData); 284 | Assert.IsInstanceOfType (typeof(Ssm2ReadAddressesRequest), p, "type"); 285 | } 286 | 287 | [Test()] 288 | public void NewFromBytes2 () 289 | { 290 | byte[] packetData = TestPacket2; 291 | var p = Ssm2ReadAddressesRequest.NewFromBytes (packetData); 292 | Assert.IsInstanceOfType (typeof(Ssm2ReadAddressesRequest), p, "type"); 293 | } 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /TestLibSSM2/TestSsm2ReadAddressesResponse.cs: -------------------------------------------------------------------------------- 1 | // TestSsm2ReadAddressesResponse.cs: Test SSM2 read addresses response class. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | using NUnit.Framework; 25 | using Subaru.SSM2; 26 | 27 | namespace Subaru.SSM2 28 | { 29 | 30 | [TestFixture()] 31 | public class TestSsm2ReadAddressesResponse 32 | { 33 | readonly byte[] TestPacket2 = { 0x80, 0xF0, 0x10, 0x03, 0xE8, 0x7D, 0xB1, 0x99 }; 34 | readonly byte[] TestPacket2Data = { 0x7D, 0xB1 }; 35 | 36 | [Test()] 37 | public void Construct2 () 38 | { 39 | byte[] packetData = TestPacket2; 40 | 41 | Ssm2ReadAddressesResponse p = new Ssm2ReadAddressesResponse (); 42 | p.Destination = Ssm2Device.DiagnosticToolF0; 43 | p.Source = Ssm2Device.Engine10; 44 | p.Data = TestPacket2Data; 45 | 46 | // should be ok after setting Data 47 | Assert.AreEqual (packetData.Length, p.Size, "Size before Construct"); 48 | 49 | p.Finish (); 50 | 51 | 52 | byte[] actual = p.ToBytesCopy (); 53 | for (int i = 0; i < packetData.Length; i++) { 54 | Assert.AreEqual (packetData[i], actual[i], "actual[" + i.ToString () + "]"); 55 | } 56 | 57 | Assert.AreEqual (packetData.Length, p.Size, "Size"); 58 | Assert.AreEqual (true, p.Check (), "Check"); 59 | 60 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Destination, "Destination"); 61 | Assert.AreEqual (Ssm2Device.Engine10, p.Source, "Source"); 62 | Assert.AreEqual (Ssm2Command.ReadAddressesResponseE8, p.Command, "Command"); 63 | 64 | IList data = p.Data; 65 | Assert.AreEqual (2, data.Count, "DataList.Count"); 66 | Assert.AreEqual (2, p.DataCount, "DataCount"); 67 | for (int i = 0; i < data.Count; i++) { 68 | Assert.AreEqual (TestPacket2Data[i], data[i], "data[" + i.ToString () + "]"); 69 | } 70 | } 71 | 72 | [Test(), ExpectedException(typeof(InvalidOperationException))] 73 | public void NotAllPropertiesSet1 () 74 | { 75 | Ssm2ReadAddressesResponse p = new Ssm2ReadAddressesResponse (); 76 | p.Source = Ssm2Device.DiagnosticToolF0; 77 | p.Data = new byte[] { 0 }; 78 | p.Finish (); 79 | } 80 | 81 | [Test(), ExpectedException(typeof(InvalidOperationException))] 82 | public void NotAllPropertiesSet2 () 83 | { 84 | Ssm2ReadAddressesResponse p = new Ssm2ReadAddressesResponse (); 85 | p.Destination = Ssm2Device.Engine10; 86 | p.Data = new byte[] { 0, 1, 2, 3, 4, 5 }; 87 | p.Finish (); 88 | } 89 | 90 | [Test(), ExpectedException(typeof(InvalidOperationException))] 91 | public void NotAllPropertiesSet3 () 92 | { 93 | Ssm2ReadAddressesResponse p = new Ssm2ReadAddressesResponse (); 94 | p.Destination = Ssm2Device.Engine10; 95 | p.Source = Ssm2Device.DiagnosticToolF0; 96 | p.Finish (); 97 | } 98 | 99 | [Test()] 100 | public void NewFromBytes2 () 101 | { 102 | byte[] packetData = TestPacket2; 103 | var p = Ssm2ReadAddressesRequest.NewFromBytes (packetData); 104 | Assert.IsInstanceOfType (typeof(Ssm2ReadAddressesResponse), p, "type"); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /TestLibSSM2/TestSsm2ReadBlockRequest.cs: -------------------------------------------------------------------------------- 1 | // TestSsm2ReadBlockRequest.cs: Test SSM2 read block request class. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using NUnit.Framework; 23 | using Subaru.SSM2; 24 | 25 | namespace Subaru.SSM2 26 | { 27 | 28 | [TestFixture()] 29 | public class TestSsm2ReadBlockRequest 30 | { 31 | /// 32 | /// Read 128 (0x80) bytes from address 0x200000, to engine from diagnostic tool. 33 | /// 34 | static readonly byte[] TestPacket1 = { 0x80, 0x10, 0xf0, 0x6, 0xa0, 0x0, 0x20, 0x0, 0x0, 0x7f, 35 | 0xc5 }; 36 | 37 | 38 | 39 | [Test()] 40 | public void Parse1 () 41 | { 42 | byte[] packetData = TestPacket1; 43 | Ssm2ReadBlockRequest p = new Ssm2ReadBlockRequest (packetData); 44 | p.FromBytes (packetData); 45 | 46 | AssertData1 (p); 47 | } 48 | 49 | [Test()] 50 | public void ConstructAndChangeProps1 () 51 | { 52 | byte[] packetData = TestPacket1; 53 | 54 | Ssm2ReadBlockRequest p = new Ssm2ReadBlockRequest (); 55 | p.Source = Ssm2Device.DiagnosticToolF0; 56 | p.Destination = Ssm2Device.Engine10; 57 | p.Address = 0x200000; 58 | p.DataCount = 128; 59 | 60 | // should be ok after setting Data but don't depend on it! 61 | Assert.AreEqual (packetData.Length, p.Size, "Size before Construct"); 62 | 63 | p.Finish (); 64 | 65 | AssertData1 (p); 66 | 67 | // changing some properties now 68 | 69 | p.DataCount = 129; 70 | // needed to calc new checksum 71 | p.Finish (); 72 | 73 | // check 74 | Assert.AreEqual (packetData.Length, p.Size, "Size2"); 75 | Assert.AreEqual (true, p.Check (), "Check2()"); 76 | Assert.AreEqual (Ssm2Device.Engine10, p.Destination, "Destination2"); 77 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Source, "Source2"); 78 | Assert.AreEqual (Ssm2Command.ReadBlockRequestA0, p.Command, "Command2"); 79 | Assert.AreEqual (0x200000, p.Address, "Address2"); 80 | Assert.AreEqual (129, p.DataCount, "DataCount2"); 81 | } 82 | 83 | [Test()] 84 | public void ConstructAndChangeProps2 () 85 | { 86 | Ssm2ReadBlockRequest p = new Ssm2ReadBlockRequest (); 87 | p.Source = Ssm2Device.DiagnosticToolF0; 88 | p.Destination = Ssm2Device.Engine10; 89 | p.Address = 0x123456; 90 | p.DataCount = 1; 91 | 92 | p.Finish (); 93 | 94 | Assert.AreEqual (11, p.Size, "Size"); 95 | Assert.AreEqual (true, p.Check (), "Check()"); 96 | 97 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Source, "Source"); 98 | Assert.AreEqual (Ssm2Device.Engine10, p.Destination, "Destination"); 99 | 100 | Assert.AreEqual (Ssm2Command.ReadBlockRequestA0, p.Command, "Command"); 101 | 102 | Assert.AreEqual (0x123456, p.Address, "Address"); 103 | Assert.AreEqual (1, p.DataCount, "DataCount"); 104 | } 105 | 106 | [Test()] 107 | public void NewFromBytes () 108 | { 109 | // best for parsing as it does not allocate anything 110 | var p = (Ssm2ReadBlockRequest)Ssm2Packet.NewFromBytes (TestPacket1); 111 | // Same static method can also be accessed like this: 112 | // Ssm2InitRequest.NewFromBytes (...) 113 | 114 | AssertData1 (p); 115 | } 116 | 117 | static void AssertData1 (Ssm2ReadBlockRequest p) 118 | { 119 | byte[] packetData = TestPacket1; 120 | 121 | Assert.AreEqual (packetData.Length, p.Size, "Size"); 122 | Assert.AreEqual (true, p.Check (), "Check()"); 123 | 124 | Assert.AreEqual (Ssm2Device.Engine10, p.Destination, "Destination"); 125 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Source, "Source"); 126 | Assert.AreEqual (Ssm2Command.ReadBlockRequestA0, p.Command, "Command"); 127 | 128 | Assert.AreEqual (0x200000, p.Address, "Address"); 129 | Assert.AreEqual (128, p.DataCount, "Data"); 130 | 131 | byte[] bytes = p.ToBytesCopy (); 132 | for (int i = 0; i < packetData.Length; i++) { 133 | Assert.AreEqual (packetData[i], bytes[i], "bytes[i]"); 134 | } 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /TestLibSSM2/TestSsm2ReadBlockResponse.cs: -------------------------------------------------------------------------------- 1 | // TestSsm2ReadBlockResponse.cs: Test SSM2 read block response class. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | using NUnit.Framework; 25 | using Subaru.SSM2; 26 | 27 | namespace Subaru.SSM2 28 | { 29 | 30 | [TestFixture()] 31 | public class TestSsm2ReadBlockResponse 32 | { 33 | readonly byte[] TestPacket1 = { 0x80, 0xF0, 0x10, 0x04, 0xE0, 0x01, 0x02, 0x03, 0x6A }; 34 | readonly byte[] TestPacket1Data = { 0x01, 0x02, 0x03 }; 35 | 36 | [Test()] 37 | public void Construct2 () 38 | { 39 | byte[] packetData = TestPacket1; 40 | byte[] sourcePayloadData = TestPacket1Data; 41 | 42 | Ssm2ReadBlockResponse p = new Ssm2ReadBlockResponse (); 43 | p.Destination = Ssm2Device.DiagnosticToolF0; 44 | p.Source = Ssm2Device.Engine10; 45 | p.Data = TestPacket1Data; 46 | 47 | // should be ok after setting Data 48 | Assert.AreEqual (packetData.Length, p.Size, "Size before Construct"); 49 | 50 | p.Finish (); 51 | 52 | 53 | byte[] actual = p.ToBytesCopy (); 54 | for (int i = 0; i < packetData.Length; i++) { 55 | Assert.AreEqual (packetData[i], actual[i], "actual[" + i.ToString () + "]"); 56 | } 57 | 58 | Assert.AreEqual (packetData.Length, p.Size, "Size"); 59 | Assert.AreEqual (true, p.Check (), "Check"); 60 | 61 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Destination, "Destination"); 62 | Assert.AreEqual (Ssm2Device.Engine10, p.Source, "Source"); 63 | Assert.AreEqual (Ssm2Command.ReadBlockResponseE0, p.Command, "Command"); 64 | 65 | IList data = p.Data; 66 | Assert.AreEqual (sourcePayloadData.Length, data.Count, "DataList.Count"); 67 | Assert.AreEqual (sourcePayloadData.Length, p.DataCount, "DataCount"); 68 | for (int i = 0; i < data.Count; i++) { 69 | Assert.AreEqual (TestPacket1Data[i], data[i], "data[" + i.ToString () + "]"); 70 | } 71 | } 72 | 73 | [Test(), ExpectedException(typeof(InvalidOperationException))] 74 | public void NotAllPropertiesSet1 () 75 | { 76 | Ssm2ReadBlockResponse p = new Ssm2ReadBlockResponse (); 77 | p.Source = Ssm2Device.DiagnosticToolF0; 78 | p.Data = new byte[] { 0 }; 79 | p.Finish (); 80 | } 81 | 82 | [Test(), ExpectedException(typeof(InvalidOperationException))] 83 | public void NotAllPropertiesSet2 () 84 | { 85 | Ssm2ReadBlockResponse p = new Ssm2ReadBlockResponse (); 86 | p.Destination = Ssm2Device.Engine10; 87 | p.Data = new byte[] { 0, 1, 2, 3, 4, 5 }; 88 | p.Finish (); 89 | } 90 | 91 | [Test(), ExpectedException(typeof(InvalidOperationException))] 92 | public void NotAllPropertiesSet3 () 93 | { 94 | Ssm2ReadBlockResponse p = new Ssm2ReadBlockResponse (); 95 | p.Destination = Ssm2Device.Engine10; 96 | p.Source = Ssm2Device.DiagnosticToolF0; 97 | p.Finish (); 98 | } 99 | 100 | [Test()] 101 | public void NewFromBytes2 () 102 | { 103 | byte[] packetData = TestPacket1; 104 | var p = Ssm2ReadBlockResponse.NewFromBytes (packetData); 105 | Assert.IsInstanceOfType (typeof(Ssm2ReadBlockResponse), p, "type"); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /TestLibSSM2/TestSsm2WriteAddressRequest.cs: -------------------------------------------------------------------------------- 1 | // TestSsm2WriteAddressRequest.cs: Test SSM2 write addresses request class. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using NUnit.Framework; 23 | using Subaru.SSM2; 24 | 25 | namespace Subaru.SSM2 26 | { 27 | 28 | [TestFixture()] 29 | public class TestSsm2WriteAddressRequest 30 | { 31 | /// 32 | /// Write value 0x02 to address 0x00006F, to engine from diagnostic tool. 33 | /// 34 | readonly byte[] TestPacket1 = { 0x80, 0x10, 0xf0, 0x5, 0xb8, 0x0, 0x0, 0x6f, 0x2, 0xae }; 35 | 36 | 37 | [Test()] 38 | public void Parse1 () 39 | { 40 | byte[] packetData = TestPacket1; 41 | var p = new Ssm2WriteAddressRequest (); 42 | p.FromBytes (packetData); 43 | 44 | Assert.AreEqual (packetData.Length, p.Size, "Size"); 45 | Assert.AreEqual (true, p.Check (), "Check()"); 46 | 47 | Assert.AreEqual (Ssm2Device.Engine10, p.Destination, "Destination"); 48 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Source, "Source"); 49 | Assert.AreEqual (Ssm2Command.WriteAddressRequestB8, p.Command, "Command"); 50 | 51 | Assert.AreEqual (0x6f, p.Address, "Address"); 52 | Assert.AreEqual (0x2, p.Data, "Data"); 53 | } 54 | 55 | [Test()] 56 | public void NewFromBytes1 () 57 | { 58 | byte[] packetData = TestPacket1; 59 | var p = Ssm2ReadAddressesRequest.NewFromBytes(packetData); 60 | Assert.IsInstanceOfType(typeof(Ssm2WriteAddressRequest), p, "type"); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /TestLibSSM2/TestSsm2WriteAddressResponse.cs: -------------------------------------------------------------------------------- 1 | // TestSsm2WriteAddressResponse.cs: Test SSM2 write addresses response class. 2 | 3 | /* Copyright (C) 2010 src0x 4 | * 5 | * This file is part of LibSSM2. 6 | * 7 | * LibSSM2 is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * LibSSM2 is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with LibSSM2. If not, see . 19 | */ 20 | 21 | 22 | using NUnit.Framework; 23 | using Subaru.SSM2; 24 | 25 | namespace Subaru.SSM2 26 | { 27 | 28 | [TestFixture()] 29 | public class TestSsm2WriteAddressResponse 30 | { 31 | /// 32 | /// Confirm written data byte 0x02, to diagnostic tool from engine. 33 | /// 34 | readonly byte[] TestPacket1 = { 0x80, 0xF0, 0x10, 0x02, 0xF8, 0x02, 0x7C }; 35 | 36 | 37 | [Test()] 38 | public void Parse1 () 39 | { 40 | byte[] packetData = TestPacket1; 41 | var p = new Ssm2WriteAddressResponse (); 42 | p.FromBytes (packetData); 43 | 44 | Assert.AreEqual (packetData.Length, p.Size, "Size"); 45 | Assert.AreEqual (true, p.Check (), "Check()"); 46 | 47 | Assert.AreEqual (Ssm2Device.DiagnosticToolF0, p.Destination, "Destination"); 48 | Assert.AreEqual (Ssm2Device.Engine10, p.Source, "Source"); 49 | Assert.AreEqual (Ssm2Command.WriteAddressResponseF8, p.Command, "Command"); 50 | 51 | Assert.AreEqual (0x2, p.Data, "Data"); 52 | } 53 | 54 | [Test()] 55 | public void NewFromBytes1 () 56 | { 57 | byte[] packetData = TestPacket1; 58 | var p = Ssm2ReadAddressesRequest.NewFromBytes (packetData); 59 | Assert.IsInstanceOfType (typeof(Ssm2WriteAddressResponse), p, "type"); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /clean_whitespace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Clean up source code or text files a bit in order 4 | # to avoid unnecessary software version control differences. 5 | 6 | # pass file list via variable FILES 7 | function CLEAN() { 8 | declare -i COUNT=0 9 | for FILE in $FILES; do 10 | let COUNT++ 11 | done 12 | 13 | declare -i NUM=0 14 | for FILE in $FILES; do 15 | let NUM++ 16 | TMPFILE="$FILE.tmp" 17 | 18 | echo -n "$NUM/$COUNT: $FILE " 19 | 20 | # remove trailing white space (spaces, tabs) 21 | # must use temp file since redirecting into input won't work 22 | sed -r 's/[[:blank:]]+$//' $FILE > $TMPFILE && mv $TMPFILE $FILE && echo "OK" 23 | done 24 | } 25 | 26 | declare FILES 27 | 28 | # find all C# files and clean them 29 | FILES=$(find . -type f -name '*.cs' ) 30 | CLEAN 31 | 32 | # same for text files 33 | FILES=$(find . -type f -name '*.txt' ) 34 | CLEAN 35 | -------------------------------------------------------------------------------- /gendarme.sh: -------------------------------------------------------------------------------- 1 | gendarme --html LibSSM2_gendarme.html LibSSM2/bin/Release/LibSSM2.dll 2 | --------------------------------------------------------------------------------