//-----------------------------------------------------------------------
//
// Copyright © 2012 Nils Hammar. All rights reserved.
//
//-----------------------------------------------------------------------
/*
* Software to access vehicle information via the OBD-II connector.
*
* Copyright © 2012 Nils Hammar
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Alternative licensing is possible, see the licensing document.
*
* The above text may not be removed or modified.
*/
//// Implementation needs to be changed to support old version (pre 04.04) of J2534.
//// #define SUPPORT_OLD_J2534
namespace DynamicApiLoading.Api.Dynamic
{
using System;
using System.Collections.Generic;
using global::Microsoft.Win32;
///
/// Class that locates J2534 DLLs by searching the registry together with their supported options.
///
public class DynamicLocater
{
///
/// Protocol name filter values.
///
private static List protocolNames = new List()
{
"J1850PWM",
"J1850VPW",
"ISO9141",
"ISO14230",
"ISO15765",
"CAN",
};
///
/// List of encountered drivers.
///
private List adapterList = new List();
///
/// Gets list of encountered drivers.
///
public IList adapters
{
get
{
return this.adapterList;
}
}
///
/// Initializes a new instance of the class.
///
public DynamicLocater()
{
RegistryKey key = Registry.LocalMachine;
RegistryKey swKey = key.OpenSubKey("SOFTWARE");
this.recursiveLookup(swKey);
}
///
/// Get a string representation of the object.
///
/// String presenting object data.
public override string ToString()
{
string txt = string.Empty;
foreach (DynamicAdapter adapter in this.adapterList)
{
txt += "Adapter: " + adapter.ToString() + "\r\n";
}
return txt;
}
///
/// Fetch a list of supported protocols for the device driver.
///
/// Registry key for device driver.
/// List of protocols supported.
private static IList getSupportedProtocols(RegistryKey vendorDeviceRk)
{
string protocolsSupportedStr = getStringValue(vendorDeviceRk, "ProtocolsSupported");
SortedDictionary sortedProtocols = new SortedDictionary();
string[] valueNames;
if (protocolsSupportedStr != null)
{
valueNames = protocolsSupportedStr.Split(new char[] { ',' });
}
else
{
valueNames = vendorDeviceRk.GetValueNames();
}
foreach (string valueName in valueNames)
{
string trimmedValueName = valueName.Trim();
if (protocolNames.Contains(trimmedValueName) && !sortedProtocols.ContainsKey(trimmedValueName))
{
sortedProtocols.Add(trimmedValueName, trimmedValueName);
}
}
IList protocols = new List();
foreach (KeyValuePair kvp in sortedProtocols)
{
protocols.Add(kvp.Key);
}
return protocols;
}
///
/// Get a value in string form from the registry.
///
/// Registry key for device driver.
/// Value name
/// String value
private static string getStringValue(RegistryKey vendorDeviceRk, string name)
{
string value = null;
try
{
if (vendorDeviceRk.GetValueKind(name) == RegistryValueKind.String)
{
value = (string)vendorDeviceRk.GetValue(name);
}
}
catch (Exception ex)
{
if (ex != null)
{
// this.iLogging.appendText("getStringValue(" + name + "):" + ex.Message + "\r\n", LogLevel.LOG_DEBUG);
}
}
return value;
}
///
/// Get a value in int form from the registry.
///
/// Notice: The returned value may be 'null' if the value doesn't exist.
///
///
/// Registry key for device driver.
/// Value name
/// int value
private static int? getIntValue(RegistryKey vendorDeviceRk, string name)
{
int? value = null;
try
{
if (vendorDeviceRk.GetValueKind(name) == RegistryValueKind.DWord)
{
object obj = vendorDeviceRk.GetValue(name);
if (obj is int)
{
value = (int)obj;
}
}
}
catch (Exception ex)
{
if (ex != null)
{
// this.iLogging.appendText("getIntValue(" + name + "):" + ex.Message + "\r\n", LogLevel.LOG_DEBUG);
}
}
return value;
}
///
/// Do a recursive lookup.
///
/// This is used since some registry keys are located in sub-locations depending
/// on if it's a 64-bit or 32-bit OS.
///
///
/// Registry key 'SOFTWARE'
private void recursiveLookup(RegistryKey swRk)
{
string[] subkeys = swRk.GetSubKeyNames();
foreach (string keyName in subkeys)
{
switch (keyName)
{
case "PassThruSupport":
#if SUPPORT_OLD_J2534
this.locateOldDevices(swRk, keyName);
#endif
break;
case "PassThruSupport.04.04":
this.locateDevices(swRk, keyName);
break;
case "Wow6432Node":
this.nextLevel(swRk, keyName);
break;
default:
break;
}
}
}
#if SUPPORT_OLD_J2534
///
/// Locate old J2534 drivers.
///
/// These drivers have a bit of a different API and
/// needs to be called a bit differently.
///
///
/// Registry key 'SOFTWARE'
/// Name of key.
private void locateOldDevices(RegistryKey swRk, string keyName)
{
RegistryKey passthruRk = swRk.OpenSubKey(keyName);
string[] vendorkeys = passthruRk.GetSubKeyNames();
foreach (string vendorkey in vendorkeys)
{
RegistryKey vendorRk = passthruRk.OpenSubKey(vendorkey);
string vendor = this.getStringValue(vendorRk, "Name");
RegistryKey vendorDevicesRk = vendorRk.OpenSubKey("Devices");
string[] devicesKeys = vendorDevicesRk.GetSubKeyNames();
foreach (string deviceKey in devicesKeys)
{
RegistryKey vendorDeviceRk = vendorDevicesRk.OpenSubKey(deviceKey);
this.addDriver(true, vendor, vendorDeviceRk, deviceKey);
}
}
}
#endif
///
/// Locate J2534 devices supporting the 04.04 version of the API.
///
/// Registry key 'SOFTWARE'
/// Name of key.
private void locateDevices(RegistryKey swRk, string keyName)
{
RegistryKey passthruRk = swRk.OpenSubKey(keyName);
string[] devicesKeys = passthruRk.GetSubKeyNames();
foreach (string deviceKey in devicesKeys)
{
RegistryKey vendorDeviceRk = passthruRk.OpenSubKey(deviceKey);
if (vendorDeviceRk != null)
{
string vendor = getStringValue(vendorDeviceRk, "Vendor");
this.addDriver(false, vendor, vendorDeviceRk, deviceKey);
}
}
}
///
/// Add one driver to the list of found drivers.
///
/// 'true' if not 04.04 version.
/// Name of vendor.
/// Registry key for vendor device.
/// Key string for device.
private void addDriver(bool oldDriver, string vendor, RegistryKey vendorDeviceRk, string deviceKey)
{
string name = getStringValue(vendorDeviceRk, "Name");
string logfile = getStringValue(vendorDeviceRk, "Logfile2534");
string configApplication = getStringValue(vendorDeviceRk, "ConfigApplication");
string j2534dll = getStringValue(vendorDeviceRk, "FunctionLibrary");
string rp1210Library = getStringValue(vendorDeviceRk, "RP1210Library");
int? rp1210DeviceId = getIntValue(vendorDeviceRk, "RP1210DeviceId");
IList protocols = getSupportedProtocols(vendorDeviceRk);
DynamicAdapter da = new DynamicAdapter(
oldDriver,
deviceKey,
name,
vendor,
logfile,
configApplication,
j2534dll,
rp1210Library,
rp1210DeviceId,
protocols);
this.adapterList.Add(da);
}
///
/// Step to next level in lookup.
///
/// Base registry key.
/// Name of sub-key.
private void nextLevel(RegistryKey key, string keyName)
{
RegistryKey key1 = key.OpenSubKey(keyName);
if (key1 != null)
{
this.recursiveLookup(key1);
}
}
}
}