Added display of fan status and temperature sensors.
This commit is contained in:
@@ -1,72 +1,163 @@
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <i2c/smbus.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "icx3.h"
|
||||
|
||||
void *print_icx3_temp(int fp)
|
||||
/* Check an I2C device file for an ICX3 controller, returns the product id, or ICX3_PRODUCT_NONE on bad read. */
|
||||
enum icx3_product_id check_for_icx3(char *i2c_dev_path)
|
||||
{
|
||||
int read_result;
|
||||
char buff[1024];
|
||||
struct icx3_fancontrol *fanstatus;
|
||||
char data[I2C_SMBUS_BLOCK_MAX] = {};
|
||||
int fd, read_result;
|
||||
struct icx3_info *temp_info;
|
||||
|
||||
fd = open(i2c_dev_path, O_RDONLY);
|
||||
if (!fd)
|
||||
return ICX3_PRODUCT_NONE;
|
||||
|
||||
if (ioctl(fd, I2C_SLAVE, ICX3_I2C_ADDR) < 0) {
|
||||
close(fd);
|
||||
return ICX3_PRODUCT_NONE;
|
||||
}
|
||||
|
||||
read_result = i2c_smbus_read_i2c_block_data(fd, ICX3_REG_READINFORMATION, ICX3_READINFORMATION_SIZE, data);
|
||||
close(fd);
|
||||
if (read_result == ICX3_READINFORMATION_SIZE) {
|
||||
temp_info = (struct icx3_info*)&data;
|
||||
if (temp_info->slave_address == ICX3_I2C_ADDR)
|
||||
return temp_info->product_id;
|
||||
}
|
||||
|
||||
return ICX3_PRODUCT_NONE;
|
||||
}
|
||||
|
||||
void print_icx3_fans(char *i2c_dev_path)
|
||||
{
|
||||
char data[I2C_SMBUS_BLOCK_MAX] = {};
|
||||
int fd, read_result;
|
||||
|
||||
struct icx3_fan_control *fan_status;
|
||||
|
||||
/* First thing is to check for the product ID to figure out how many fans we have */
|
||||
int fans_avail[ICX3_MAX_FANS] = {0};
|
||||
int product_id = check_for_icx3(i2c_dev_path);
|
||||
|
||||
/* From ICX3TotalFanCtrl.cs */
|
||||
switch(product_id) {
|
||||
case ICX3_PRODUCT_E221_E222_XC3:
|
||||
case ICX3_PRODUCT_E229_XC3:
|
||||
case ICX3_PRODUCT_E222_XC3_LPC54113:
|
||||
case ICX3_PRODUCT_E229_XC3_LPC54113:
|
||||
case ICX3_PRODUCT_E221_XC3_STM32L431:
|
||||
case ICX3_PRODUCT_E229_E237_XC3_STM32L431:
|
||||
/* XC3, default plus fan 3 */
|
||||
fans_avail[0] = 1;
|
||||
fans_avail[1] = 1;
|
||||
fans_avail[2] = 1;
|
||||
break;
|
||||
case ICX3_PRODUCT_E227_E228_FTW3:
|
||||
case ICX3_PRODUCT_E230_FTW3:
|
||||
case ICX3_PRODUCT_E227_E228_FTW3_LPC54113:
|
||||
case ICX3_PRODUCT_E230_FTW3_LPC54113:
|
||||
case ICX3_PRODUCT_E230_E238_FTW3_STM32L431:
|
||||
case ICX3_PRODUCT_E250_FTW3:
|
||||
/* FTW3, default plus fan 3 and external fan */
|
||||
fans_avail[0] = 1;
|
||||
fans_avail[1] = 1;
|
||||
fans_avail[2] = 1;
|
||||
fans_avail[3] = 1;
|
||||
break;
|
||||
case ICX3_PRODUCT_E223_KINGPIN_HYBRID:
|
||||
case ICX3_PRODUCT_E227_E228_FTW3_HYBRID:
|
||||
case ICX3_PRODUCT_E251_KINGPIN_HYBRID:
|
||||
case ICX3_PRODUCT_E227_E228_FTW3_HYBRID_LPC54113:
|
||||
case ICX3_PRODUCT_E250_FTW3_HYBRID:
|
||||
/* KINGPIN, default and external */
|
||||
fans_avail[0] = 1;
|
||||
fans_avail[1] = 1;
|
||||
fans_avail[3] = 1;
|
||||
break;
|
||||
case ICX3_PRODUCT_E227_E228_FTW3_HC:
|
||||
case ICX3_PRODUCT_E223_KINGPIN_HC:
|
||||
case ICX3_PRODUCT_E251_KINGPIN_HC:
|
||||
/* External fan only */
|
||||
fans_avail[3] = 1;
|
||||
break;
|
||||
default:
|
||||
fans_avail[0] = 1;
|
||||
fans_avail[1] = 1;
|
||||
break;
|
||||
case ICX3_PRODUCT_E221_E222_XC3_HC:
|
||||
/* Not sure what this case is for */
|
||||
break;
|
||||
}
|
||||
|
||||
fd = open(i2c_dev_path, O_RDONLY);
|
||||
|
||||
/* Error silently here because we should have already checked we can read the i2c in check_for_icx3() */
|
||||
if (!fd)
|
||||
return;
|
||||
if (ioctl(fd, I2C_SLAVE, ICX3_I2C_ADDR) < 0) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=0; i < ICX3_MAX_FANS; i++) {
|
||||
read_result = i2c_smbus_read_i2c_block_data(fp, ICX3_REG_FANCONTROL + i, ICX3_FANCONTROL_SIZE, buff);
|
||||
if (!fans_avail[i])
|
||||
continue;
|
||||
|
||||
read_result = i2c_smbus_read_i2c_block_data(fd, ICX3_REG_FANCONTROL + i, ICX3_FANCONTROL_SIZE, data);
|
||||
if (read_result != ICX3_FANCONTROL_SIZE) {
|
||||
return 0;
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
fanstatus = (struct icx3_fancontrol*) &buff;
|
||||
fan_status = (struct icx3_fan_control*) &data;
|
||||
printf("%s: %d RPM (%d/%d%%, %s)\n",
|
||||
icx3_fan_names[i],
|
||||
fanstatus->rpm_status,
|
||||
fanstatus->duty_status,
|
||||
fanstatus->duty,
|
||||
icx3_fan_mode_names[fanstatus->fanmode]
|
||||
fan_status->rpm_status,
|
||||
fan_status->duty_status,
|
||||
fan_status->duty,
|
||||
icx3_fan_mode_names[fan_status->fanmode]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void print_icx3_temps(char *i2c_dev_path)
|
||||
{
|
||||
char data[I2C_SMBUS_BLOCK_MAX] = {};
|
||||
int fd, read_result;
|
||||
struct icx3_temp_sensors *temp_sensors;
|
||||
|
||||
struct icx3_tempsensors *tempsensors;
|
||||
read_result = i2c_smbus_read_i2c_block_data(fp, ICX3_REG_TEMPSENSOR, ICX3_TEMPSENSOR_SIZE, buff);
|
||||
if (read_result != ICX3_TEMPSENSOR_SIZE) {
|
||||
return 0;
|
||||
fd = open(i2c_dev_path, O_RDONLY);
|
||||
|
||||
/* Error silently here because we should have already checked we can read the i2c in check_for_icx3() */
|
||||
if (!fd)
|
||||
return;
|
||||
if (ioctl(fd, I2C_SLAVE, ICX3_I2C_ADDR) < 0) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
tempsensors = (struct icx3_tempsensors*) &buff;
|
||||
|
||||
read_result = i2c_smbus_read_i2c_block_data(fd, ICX3_REG_TEMPSENSOR, ICX3_TEMPSENSOR_SIZE, data);
|
||||
if (read_result != ICX3_TEMPSENSOR_SIZE) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
temp_sensors = (struct icx3_temp_sensors*) &data;
|
||||
|
||||
float cur_temp;
|
||||
short cur_data;
|
||||
|
||||
for (int i=0; i<ICX3_NUM_TEMP_SENSORS; i++) {
|
||||
cur_data = (short)(tempsensors->data[2*i+1] << 8) | (short)(tempsensors->data[2*i]);
|
||||
/* endian swap */
|
||||
cur_data = (short)(temp_sensors->data[2*i+1] << 8) | (short)(temp_sensors->data[2*i]);
|
||||
/* temp is reported in tenths of deg C */
|
||||
cur_temp = (float)cur_data/10;
|
||||
printf("%s %.1f C\n",
|
||||
icx3_temp_sensor_names[i],
|
||||
cur_temp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check an I2C device file for an ICX3 controller, returs the product id. */
|
||||
enum icx3_product_id check_for_icx3(char *i2c_dev_path)
|
||||
{
|
||||
char data[I2C_SMBUS_BLOCK_MAX] = {};
|
||||
int test_fd, read_result;
|
||||
struct icx3_info *temp_info;
|
||||
|
||||
test_fd = fopen(i2c_dev_path, O_RDONLY);
|
||||
if (!test_fd)
|
||||
return ICX3_NONE;
|
||||
|
||||
if (ioctl(test_fd, I2C_SLAVE, ICX3_I2C_ADDR) < 0) {
|
||||
close(test_fd);
|
||||
return ICX3_NONE;
|
||||
}
|
||||
|
||||
read_result = i2c_smbus_read_i2c_block_data(test_fd, ICX3_REG_READINFORMATION, ICX3_READINFORMATION_SIZE, buff);
|
||||
if (read_result == ICX3_READINFORMATION_SIZE) {
|
||||
temp_info = (struct *icx3_info)&buff;
|
||||
if (temp_info->slave_address == ICX3_I2C_ADDR)
|
||||
return temp_info->product_id;
|
||||
}
|
||||
|
||||
return ICX3_NONE;
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user