Skip to content

Commit

Permalink
Implement ECDevicesNUC resource generation with SMC support
Browse files Browse the repository at this point in the history
closes #56
  • Loading branch information
osy authored and vit9696 committed Mar 30, 2021
1 parent 747687f commit 554b288
Show file tree
Hide file tree
Showing 21 changed files with 2,970 additions and 324 deletions.
2 changes: 1 addition & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ VirtualSMC Changelog
- Added SuperIO device activation when it is disabled on probe
- Added support for Nuvoton NCT6796D-E (0xD42A)
- Added support for ITE IT8987 (requires DEBUG firmware, not available for public)
- Added Intel NUC FAN monitoring (requires manual configuration via `ec-device`, see `EmbeddedControllers.md`)
- Added Intel NUC monitoring (requires manual configuration via `ec-device`, see `EmbeddedControllers.md`)

#### v1.2.1
- Fix version publishing for VirtualSMC and plugins
Expand Down
189 changes: 158 additions & 31 deletions Sensors/SMCSuperIO/DeviceGenerator/main.mm
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
#include \"NuvotonDevice.hpp\"\n\
#include \"FintekDevice.hpp\"\n\
#include \"ITEDevice.hpp\"\n\
#include \"WinbondDevice.hpp\"\n\n"
#include \"WinbondDevice.hpp\"\n\
#include \"ECDeviceNUC.hpp\"\n\n"
};

static void appendFile(NSString *file, NSString *data) {
Expand All @@ -39,25 +40,56 @@ static void appendFile(NSString *file, NSString *data) {
static constexpr uint8_t WinbondHardwareMonitorLDN = 0x0B;
static constexpr uint8_t FintekITEHardwareMonitorLDN = 0x04;

static NSString *generateSensor(NSArray *sensors, NSString *sensorReading, NSString *sensorKind, NSString *valueType) {
static NSString *generateSensorRead(NSArray *sensors, NSString *sensorReading, NSString *sensorKind, NSString *valueType) {
if (!sensors) {
return @"";
}
NSString *capitalizedSensorKind = [sensorKind capitalizedString];
NSMutableString *sensorsContents = [NSMutableString stringWithCapacity: 1024];
[sensorsContents appendString:@"public:\n"];
// uint8_t getTachometerCount()
[sensorsContents appendFormat: @"\tuint8_t get%@Count() override {\n\t\treturn %lu;\n\t}\n\n", capitalizedSensorKind, [sensors count]];

NSMutableString *inlineReading = [NSMutableString stringWithCapacity: 1024];
BOOL hasInlineReading = NO;
[inlineReading appendString:@"\t\tswitch (index) {\n"];
for (int i = 0; i < sensors.count; i++) {
NSDictionary *sensor = sensors[i];
NSString *readValue = sensor[@"ReadValue"];
if (readValue) {
[inlineReading appendFormat:@"\t\t\tcase %d: return %@;\n", i, readValue];
hasInlineReading = YES;
}
}
[inlineReading appendFormat:@"\t\t\tdefault: break;\n\t\t}\n"];
// uint16_t updateTachometer(uint8_t index)
if (!sensorReading) {
sensorReading = [NSString stringWithFormat:@"%@Read", sensorKind];
}
[sensorsContents appendFormat: @"\t%@ update%@(uint8_t index) override {\n\t\treturn %@(index);\n\t}\n\n", valueType, capitalizedSensorKind, sensorReading];

// const char* getTachometerName(uint8_t index);
[sensorsContents appendFormat: @"\tconst char* get%@Name(uint8_t index) override {\n\t\tif (index < get%@Count()) {\n\t\t\treturn %@Names[index];\n\t\t}\n\t\treturn nullptr;\n\t}\n\n", capitalizedSensorKind, capitalizedSensorKind, sensorKind];
[sensorsContents appendFormat: @"\t%@ update%@(uint8_t index) override {\n%@\t\treturn %@(index);\n\t}\n\n", valueType, capitalizedSensorKind, hasInlineReading ? inlineReading : @"", sensorReading];
return sensorsContents;
}

static NSString *generateSensorNames(NSArray *sensors, NSString *sensorKind) {
if (!sensors) {
return @"";
}
NSString *capitalizedSensorKind = [sensorKind capitalizedString];
NSMutableString *sensorsContents = [NSMutableString stringWithCapacity: 1024];
NSMutableString *inlineNames = [NSMutableString stringWithCapacity: 1024];
BOOL hasInlineNames = NO;
[sensorsContents appendFormat: @"\tconst char* get%@Name(uint8_t index) override {\n", capitalizedSensorKind];
[inlineNames appendString:@"\t\tswitch (index) {\n"];
for (int i = 0; i < sensors.count; i++) {
NSDictionary *sensor = sensors[i];
NSString *nameValue = sensor[@"NameValue"];
if (nameValue) {
[inlineNames appendFormat:@"\t\t\tcase %d: return %@;\n", i, nameValue];
hasInlineNames = YES;
}
}
[inlineNames appendString:@"\t\t\tdefault: break;\n\t\t}\n"];
if (hasInlineNames) {
[sensorsContents appendString:inlineNames];
}

uint32_t index = 0;
NSMutableString *sensorNames = [NSMutableString stringWithFormat:@"private:\n\tconst char* %@Names[%lu] = {\n", sensorKind, [sensors count]];
for (NSDictionary *sensor in sensors) {
Expand All @@ -69,14 +101,83 @@ static void appendFile(NSString *file, NSString *data) {
}
if ([sensors count] == index) {
[sensorNames appendString: @"\t};\n"];
[sensorsContents appendFormat: @"\t\tif (index < get%@Count()) {\n\t\t\treturn %@Names[index];\n\t\t}\n\t\treturn nullptr;\n\t}\n\n", capitalizedSensorKind, sensorKind];
[sensorsContents appendString: sensorNames];
} else {
SYSLOG("Not all names for tachometers provided in the descriptor.");
[sensorsContents appendString: @"\t\treturn nullptr;\n\t}\n\n"];
}
return sensorsContents;
}

static NSString *generateSensors(NSArray *sensors, NSString *sensorReading, NSString *sensorKind, NSString *valueType) {
if (!sensors) {
return @"";
}
NSString *capitalizedSensorKind = [sensorKind capitalizedString];
NSMutableString *sensorsContents = [NSMutableString stringWithCapacity: 1024];
[sensorsContents appendString:@"public:\n"];
// uint8_t getTachometerCount()
[sensorsContents appendFormat: @"\tuint8_t get%@Count() override {\n\t\treturn %lu;\n\t}\n\n", capitalizedSensorKind, [sensors count]];
// uint16_t updateTachometer()
[sensorsContents appendString:generateSensorRead(sensors, sensorReading, sensorKind, valueType)];

// const char* getTachometerName(uint8_t index);
[sensorsContents appendString:generateSensorNames(sensors, sensorKind)];

return sensorsContents;
}

static NSString *generateSensorSmcKeys(NSArray *sensors, NSString *sensorKind) {
if (!sensors) {
return @"";
}
NSString *capitalizedSensorKind = [sensorKind capitalizedString];
NSMutableString *sensorsContents = [NSMutableString stringWithCapacity: 1024];
BOOL hasSmcKey = NO;
[sensorsContents appendString:@"protected:\n"];
[sensorsContents appendFormat:@"\tvoid setup%@Keys(VirtualSMCAPI::Plugin &vsmcPlugin) override {\n", capitalizedSensorKind];
for (int i = 0; i < sensors.count; i++) {
NSDictionary *sensor = sensors[i];
NSString *smcKey = sensor[@"SmcKey"];
NSString *smcKeyType = sensor[@"SmcKeyType"];
if (!smcKeyType) {
smcKeyType = @"SmcKeyTypeFloat";
}
if (smcKey) {
NSString *valueFunc = @"";
BOOL hasKeyTypeArg = NO;
if ([smcKeyType isEqualToString:@"SmcKeyTypeFloat"]) {
valueFunc = @"valueWithFlt";
} else if ([smcKeyType isEqualToString:@"SmcKeyTypeFlag"]) {
valueFunc = @"valueWithFlag";
} else if ([smcKeyType hasPrefix:@"SmcKeyTypeUint"]) {
NSString *bitWidth = [smcKeyType substringFromIndex:14];
valueFunc = [@"valueWithUint" stringByAppendingString:bitWidth];
} else if ([smcKeyType hasPrefix:@"SmcKeyTypeSint"]) {
NSString *bitWidth = [smcKeyType substringFromIndex:14];
valueFunc = [@"valueWithSint" stringByAppendingString:bitWidth];
} else if ([smcKeyType hasPrefix:@"SmcKeyTypeFp"]) {
valueFunc = @"valueWithFp";
hasKeyTypeArg = YES;
} else if ([smcKeyType hasPrefix:@"SmcKeyTypeSp"]) {
valueFunc = @"valueWithSp";
hasKeyTypeArg = YES;
} else {
SYSLOG("Unsupported SMC key type: %s, skipping.", smcKeyType.UTF8String);
continue;
}
[sensorsContents appendFormat:@"\t\tVirtualSMCAPI::addKey(%@, vsmcPlugin.data, VirtualSMCAPI::%@(0, %@%@ new %@Key(getSmcSuperIO(), this, %d)));\n", smcKey, valueFunc, hasKeyTypeArg ? smcKeyType : @"", hasKeyTypeArg ? @"," : @"", capitalizedSensorKind, i];
hasSmcKey = YES;
}
}
[sensorsContents appendString:@"\t}\n"];
if (hasSmcKey) {
return sensorsContents;
} else {
return @"";
}
}

static NSString *processDevice(NSDictionary *deviceDict, NSString *deviceClassName, NSMutableString *factoryMethodContents, uint32_t index) {
NSString *deviceNamespace = nil;
uint8_t defaultLdn = 0xFF;
Expand All @@ -97,6 +198,8 @@ static void appendFile(NSString *file, NSString *data) {
deviceNamespace = @"ITE";
if (![deviceDict objectForKey:@"UsesEC"])
defaultLdn = FintekITEHardwareMonitorLDN;
} else if ([deviceClassName hasPrefix:@"ECDevice"]) {
deviceNamespace = @"EC";
} else {
SYSLOG("Unknown BaseClassName specified: %s, skipping the descriptor.", [deviceNamespace UTF8String]);
return @"";
Expand Down Expand Up @@ -126,37 +229,53 @@ static void appendFile(NSString *file, NSString *data) {
return @"";
}
// tachometers
[baseClassContents appendString: generateSensor([sensors objectForKey:@"Tachometer"], [sensors objectForKey:@"TachometerReading"], @"tachometer", @"uint16_t")];
[baseClassContents appendString: generateSensors([sensors objectForKey:@"Tachometer"], [sensors objectForKey:@"TachometerReading"], @"tachometer", @"uint16_t")];
// voltages
[baseClassContents appendString: generateSensor([sensors objectForKey:@"Voltage"], [sensors objectForKey:@"VoltageReading"], @"voltage", @"float")];
[baseClassContents appendString: generateSensors([sensors objectForKey:@"Voltage"], [sensors objectForKey:@"VoltageReading"], @"voltage", @"float")];
[baseClassContents appendString: generateSensorSmcKeys([sensors objectForKey:@"Voltage"], @"voltage")];
// temperatures
[baseClassContents appendString: generateSensors([sensors objectForKey:@"Temperature"], [sensors objectForKey:@"TemperatureReading"], @"temperature", @"float")];
[baseClassContents appendString: generateSensorSmcKeys([sensors objectForKey:@"Temperature"], @"temperature")];
[baseClassContents appendString: @"\n};\n\n"];

for (NSDictionary *compDevice in compatibleDevices) {
NSNumber *deviceID = [compDevice objectForKey: @"DeviceID"];
if (deviceID == nil) {
SYSLOG("No DeviceID key specified for the compatible device, skipping this entry.");
continue;
}
auto classContents = [NSMutableString stringWithFormat:@"class Device_0x%04X final : public %@ {\npublic:\n", [deviceID intValue], deviceGeneratedClassName];
// factory method
NSNumber *deviceIdMask = [compDevice objectForKey: @"DeviceIDMask"];
NSString *deviceIdTest;
if (deviceIdMask != nil) {
deviceIdTest = [NSString stringWithFormat: @"(deviceId & 0x%04X)", [deviceIdMask intValue]];
NSMutableString *classContents = nil;
if ([deviceClassName hasPrefix:@"ECDevice"]) {
NSString *matchName = compDevice[@"MatchName"];
if (!matchName) {
SYSLOG("No DisplayName or MatchName specified for the compatible device, skipping this entry.");
continue;
}
classContents = [NSMutableString stringWithFormat:@"class Device_%@ final : public %@ {\npublic:\n", matchName, deviceGeneratedClassName];
[classContents appendFormat: @"\tstatic SuperIODevice *createDevice(const char *name) {\n\t\tif (strcmp(name, \"%@\") == 0)\n\t\t\treturn new Device_%@();\n\t\treturn nullptr;\n\t}\n\n", matchName, matchName];
[factoryMethodContents appendFormat: @"\tdevice = Device_%@::createDevice(name);\n\tif (device) return device;\n", matchName];
} else {
deviceIdTest = @"deviceId";
NSNumber *deviceID = [compDevice objectForKey: @"DeviceID"];
if (deviceID == nil) {
SYSLOG("No DeviceID key specified for the compatible device, skipping this entry.");
continue;
}
classContents = [NSMutableString stringWithFormat:@"class Device_0x%04X final : public %@ {\npublic:\n", [deviceID intValue], deviceGeneratedClassName];
// factory method
NSNumber *deviceIdMask = [compDevice objectForKey: @"DeviceIDMask"];
NSString *deviceIdTest;
if (deviceIdMask != nil) {
deviceIdTest = [NSString stringWithFormat: @"(deviceId & 0x%04X)", [deviceIdMask intValue]];
} else {
deviceIdTest = @"deviceId";
}
[classContents appendFormat: @"\tstatic SuperIODevice *createDevice(uint16_t deviceId) {\n\t\tif (%@ == 0x%04X)\n\t\t\treturn new Device_0x%04X();\n\t\treturn nullptr;\n\t}\n\n", deviceIdTest, [deviceID intValue], [deviceID intValue]];
// uint8_t getLdn()
NSNumber *ldn = [compDevice objectForKey: @"LDN"]; // optional key
[classContents appendFormat: @"\tuint8_t getLdn() override {\n\t\treturn 0x%02X;\n\t}\n\n", ldn != nil ? [ldn intValue] : defaultLdn];
[factoryMethodContents appendFormat: @"\tdevice = Device_0x%04X::createDevice(deviceId);\n\tif (device) return device;\n", [deviceID intValue]];
}
[classContents appendFormat: @"\tstatic SuperIODevice *createDevice(uint16_t deviceId) {\n\t\tif (%@ == 0x%04X)\n\t\t\treturn new Device_0x%04X();\n\t\treturn nullptr;\n\t}\n\n", deviceIdTest, [deviceID intValue], [deviceID intValue]];
// uint8_t getLdn()
NSNumber *ldn = [compDevice objectForKey: @"LDN"]; // optional key
[classContents appendFormat: @"\tuint8_t getLdn() override {\n\t\treturn 0x%02X;\n\t}\n\n", ldn != nil ? [ldn intValue] : defaultLdn];
// const char* getModelName()
NSString *displayName = [compDevice objectForKey: @"DisplayName"];
if (!displayName) {
displayName = @"<Unspecified>";
}
[classContents appendFormat: @"\tconst char* getModelName() override {\n\t\treturn \"%@\";\n\t}\n\n", displayName];
[factoryMethodContents appendFormat: @"\tdevice = Device_0x%04X::createDevice(deviceId);\n\tif (device) return device;\n", [deviceID intValue]];
[classContents appendString: @"};\n\n"];
[baseClassContents appendString: classContents];
}
Expand Down Expand Up @@ -198,6 +317,7 @@ int main(int argc, const char * argv[]) {
// Device factory
NSMutableString *factoryMethodContentsGeneric = [NSMutableString stringWithString: @"SuperIODevice *createDevice(uint16_t deviceId) {\n\tSuperIODevice *device;\n"];
NSMutableString *factoryMethodContentsITE = [NSMutableString stringWithString: @"SuperIODevice *createDeviceITE(uint16_t deviceId) {\n\tSuperIODevice *device;\n"];
NSMutableString *factoryMethodContentsEC = [NSMutableString stringWithString: @"SuperIODevice *createDeviceEC(const char *name) {\n\tSuperIODevice *device;\n"];

uint32_t i = 0;
for (NSDictionary *deviceDict in files) {
Expand All @@ -207,12 +327,19 @@ int main(int argc, const char * argv[]) {
SYSLOG("No BaseClassName key specified, skipping the descriptor.");
continue;
}
NSMutableString *factoryMethodContents = [deviceClassName hasPrefix:@"ITE"] ? factoryMethodContentsITE : factoryMethodContentsGeneric;
NSMutableString *factoryMethodContents = factoryMethodContentsGeneric;
if ([deviceClassName hasPrefix:@"ITE"]) {
factoryMethodContents = factoryMethodContentsITE;
} else if ([deviceClassName hasPrefix:@"ECDevice"]) {
factoryMethodContents = factoryMethodContentsEC;
}
auto fileContents = processDevice(deviceDict, deviceClassName, factoryMethodContents, i++);
appendFile(outputCpp, fileContents);
}
[factoryMethodContentsGeneric appendString: @"\treturn nullptr;\n}\n"];
[factoryMethodContentsITE appendString: @"\treturn nullptr;\n}\n"];
[factoryMethodContentsEC appendString: @"\treturn nullptr;\n}\n"];
appendFile(outputCpp, factoryMethodContentsGeneric);
appendFile(outputCpp, factoryMethodContentsITE);
appendFile(outputCpp, factoryMethodContentsEC);
}
Loading

0 comments on commit 554b288

Please sign in to comment.