#include <linux/bitops.h>
#include <linux/completion.h>
#include <linux/debugfs.h>
#include <linux/hid.h>
#include <linux/hwmon.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#define USB_VENDOR_ID_CORSAIR …
#define USB_PRODUCT_ID_CORSAIR_COMMANDERPRO …
#define USB_PRODUCT_ID_CORSAIR_1000D …
#define OUT_BUFFER_SIZE …
#define IN_BUFFER_SIZE …
#define LABEL_LENGTH …
#define REQ_TIMEOUT …
#define CTL_GET_FW_VER …
#define CTL_GET_BL_VER …
#define CTL_GET_TMP_CNCT …
#define CTL_GET_TMP …
#define CTL_GET_VOLT …
#define CTL_GET_FAN_CNCT …
#define CTL_GET_FAN_RPM …
#define CTL_GET_FAN_PWM …
#define CTL_SET_FAN_FPWM …
#define CTL_SET_FAN_TARGET …
#define NUM_FANS …
#define NUM_TEMP_SENSORS …
struct ccp_device { … };
static int ccp_get_errno(struct ccp_device *ccp)
{ … }
static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2, u8 byte3)
{ … }
static int ccp_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size)
{ … }
static int get_data(struct ccp_device *ccp, int command, int channel, bool two_byte_data)
{ … }
static int set_pwm(struct ccp_device *ccp, int channel, long val)
{ … }
static int set_target(struct ccp_device *ccp, int channel, long val)
{ … }
static int ccp_read_string(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, const char **str)
{ … }
static int ccp_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
struct ccp_device *ccp = dev_get_drvdata(dev);
int ret;
switch (type) {
case hwmon_temp:
switch (attr) {
case hwmon_temp_input:
ret = get_data(ccp, CTL_GET_TMP, channel, true);
if (ret < 0)
return ret;
*val = ret * 10;
return 0;
default:
break;
}
break;
case hwmon_fan:
switch (attr) {
case hwmon_fan_input:
ret = get_data(ccp, CTL_GET_FAN_RPM, channel, true);
if (ret < 0)
return ret;
*val = ret;
return 0;
case hwmon_fan_target:
if (ccp->target[channel] < 0)
return -ENODATA;
*val = ccp->target[channel];
return 0;
default:
break;
}
break;
case hwmon_pwm:
switch (attr) {
case hwmon_pwm_input:
ret = get_data(ccp, CTL_GET_FAN_PWM, channel, false);
if (ret < 0)
return ret;
*val = DIV_ROUND_CLOSEST(ret * 255, 100);
return 0;
default:
break;
}
break;
case hwmon_in:
switch (attr) {
case hwmon_in_input:
ret = get_data(ccp, CTL_GET_VOLT, channel, true);
if (ret < 0)
return ret;
*val = ret;
return 0;
default:
break;
}
break;
default:
break;
}
return -EOPNOTSUPP;
};
static int ccp_write(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long val)
{
struct ccp_device *ccp = dev_get_drvdata(dev);
switch (type) {
case hwmon_pwm:
switch (attr) {
case hwmon_pwm_input:
return set_pwm(ccp, channel, val);
default:
break;
}
break;
case hwmon_fan:
switch (attr) {
case hwmon_fan_target:
return set_target(ccp, channel, val);
default:
break;
}
break;
default:
break;
}
return -EOPNOTSUPP;
};
static umode_t ccp_is_visible(const void *data, enum hwmon_sensor_types type,
u32 attr, int channel)
{
const struct ccp_device *ccp = data;
switch (type) {
case hwmon_temp:
if (!test_bit(channel, ccp->temp_cnct))
break;
switch (attr) {
case hwmon_temp_input:
return 0444;
case hwmon_temp_label:
return 0444;
default:
break;
}
break;
case hwmon_fan:
if (!test_bit(channel, ccp->fan_cnct))
break;
switch (attr) {
case hwmon_fan_input:
return 0444;
case hwmon_fan_label:
return 0444;
case hwmon_fan_target:
return 0644;
default:
break;
}
break;
case hwmon_pwm:
if (!test_bit(channel, ccp->fan_cnct))
break;
switch (attr) {
case hwmon_pwm_input:
return 0644;
default:
break;
}
break;
case hwmon_in:
switch (attr) {
case hwmon_in_input:
return 0444;
default:
break;
}
break;
default:
break;
}
return 0;
};
static const struct hwmon_ops ccp_hwmon_ops = …;
static const struct hwmon_channel_info * const ccp_info[] = …;
static const struct hwmon_chip_info ccp_chip_info = …;
static int get_fan_cnct(struct ccp_device *ccp)
{ … }
static int get_temp_cnct(struct ccp_device *ccp)
{ … }
static int get_fw_version(struct ccp_device *ccp)
{ … }
static int get_bl_version(struct ccp_device *ccp)
{ … }
static int firmware_show(struct seq_file *seqf, void *unused)
{ … }
DEFINE_SHOW_ATTRIBUTE(…);
static int bootloader_show(struct seq_file *seqf, void *unused)
{ … }
DEFINE_SHOW_ATTRIBUTE(…);
static void ccp_debugfs_init(struct ccp_device *ccp)
{ … }
static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
{ … }
static void ccp_remove(struct hid_device *hdev)
{ … }
static const struct hid_device_id ccp_devices[] = …;
static struct hid_driver ccp_driver = …;
MODULE_DEVICE_TABLE(hid, ccp_devices);
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;
static int __init ccp_init(void)
{ … }
static void __exit ccp_exit(void)
{ … }
late_initcall(ccp_init);
module_exit(ccp_exit);