This adds fan_target entries to the corsair-cpro driver.
Reading the attribute from the device does not seem possible, so
it returns the last set value. (same as pwm)
send_usb_cmd now has one more argument, which is needed for the
fan_target command.
Signed-off-by: Marius Zachmann <[email protected]>
---
Change from v1:
- use clamp_val instead of bounds checking
---
Documentation/hwmon/corsair-cpro.rst | 3 ++
drivers/hwmon/corsair-cpro.c | 61 ++++++++++++++++++++++------
2 files changed, 52 insertions(+), 12 deletions(-)
diff --git a/Documentation/hwmon/corsair-cpro.rst b/Documentation/hwmon/corsair-cpro.rst
index 5913e23d764c..78820156f07d 100644
--- a/Documentation/hwmon/corsair-cpro.rst
+++ b/Documentation/hwmon/corsair-cpro.rst
@@ -33,6 +33,9 @@ in2_input Voltage on SATA 3.3v
temp[1-4]_input Temperature on connected temperature sensors
fan[1-6]_input Connected fan rpm.
fan[1-6]_label Shows fan type as detected by the device.
+fan[1-6]_target Sets fan speed target rpm.
+ When reading, it reports the last value if it was set by the driver.
+ Otherwise returns 0.
pwm[1-6] Sets the fan speed. Values from 0-255.
When reading, it reports the last value if it was set by the driver.
Otherwise returns 0.
diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c
index a22583acc229..fe625190e3a1 100644
--- a/drivers/hwmon/corsair-cpro.c
+++ b/drivers/hwmon/corsair-cpro.c
@@ -5,8 +5,8 @@
*/
#include <linux/bitops.h>
-#include <linux/kernel.h>
#include <linux/hwmon.h>
+#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
@@ -51,6 +51,12 @@
* send: byte 1 is fan number
* send: byte 2 is percentage from 0 - 100
*/
+#define CTL_SET_FAN_TARGET 0x24 /*
+ * set target rpm
+ * send: byte 1 is fan number
+ * send: byte 2-3 is target
+ * device accepts all values from 0x00 - 0xFFFF
+ */
#define NUM_FANS 6
#define NUM_TEMP_SENSORS 4
@@ -60,13 +66,14 @@ struct ccp_device {
struct mutex mutex; /* whenever buffer is used, lock before send_usb_cmd */
u8 *buffer;
int pwm[6];
+ int target[6];
DECLARE_BITMAP(temp_cnct, NUM_TEMP_SENSORS);
DECLARE_BITMAP(fan_cnct, NUM_FANS);
char fan_label[6][LABEL_LENGTH];
};
/* send command, check for error in response, response in ccp->buffer */
-static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2)
+static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2, u8 byte3)
{
int actual_length;
int ret;
@@ -75,6 +82,7 @@ static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2)
ccp->buffer[0] = command;
ccp->buffer[1] = byte1;
ccp->buffer[2] = byte2;
+ ccp->buffer[3] = byte3;
ret = usb_bulk_msg(ccp->udev, usb_sndintpipe(ccp->udev, 2), ccp->buffer, OUT_BUFFER_SIZE,
&actual_length, 1000);
@@ -103,7 +111,7 @@ static int get_data(struct ccp_device *ccp, int command, int channel)
mutex_lock(&ccp->mutex);
- ret = send_usb_cmd(ccp, command, channel, 0);
+ ret = send_usb_cmd(ccp, command, channel, 0, 0);
if (ret)
goto out_unlock;
@@ -128,7 +136,22 @@ static int set_pwm(struct ccp_device *ccp, int channel, long val)
mutex_lock(&ccp->mutex);
- ret = send_usb_cmd(ccp, CTL_SET_FAN_FPWM, channel, val);
+ ret = send_usb_cmd(ccp, CTL_SET_FAN_FPWM, channel, val, 0);
+
+ mutex_unlock(&ccp->mutex);
+ return ret;
+}
+
+static int set_target(struct ccp_device *ccp, int channel, long val)
+{
+ int ret;
+
+ val = clamp_val(val, 0, 0xFFFF);
+ ccp->target[channel] = val;
+
+ mutex_lock(&ccp->mutex);
+
+ ret = send_usb_cmd(ccp, CTL_SET_FAN_TARGET, channel, val >> 8, val);
mutex_unlock(&ccp->mutex);
return ret;
@@ -183,6 +206,11 @@ static int ccp_read(struct device *dev, enum hwmon_sensor_types type,
return ret;
*val = ret;
return 0;
+ case hwmon_fan_target:
+ /* how to read target values from the device is unknown */
+ /* driver returns last set value or 0 */
+ *val = ccp->target[channel];
+ return 0;
default:
break;
}
@@ -231,6 +259,13 @@ static int ccp_write(struct device *dev, enum hwmon_sensor_types type,
break;
}
break;
+ case hwmon_fan:
+ switch (attr) {
+ case hwmon_fan_target:
+ return set_target(ccp, channel, val);
+ default:
+ break;
+ }
default:
break;
}
@@ -266,6 +301,8 @@ static umode_t ccp_is_visible(const void *data, enum hwmon_sensor_types type,
return 0444;
case hwmon_fan_label:
return 0444;
+ case hwmon_fan_target:
+ return 0644;
default:
break;
}
@@ -313,12 +350,12 @@ static const struct hwmon_channel_info *ccp_info[] = {
HWMON_T_INPUT
),
HWMON_CHANNEL_INFO(fan,
- HWMON_F_INPUT | HWMON_F_LABEL,
- HWMON_F_INPUT | HWMON_F_LABEL,
- HWMON_F_INPUT | HWMON_F_LABEL,
- HWMON_F_INPUT | HWMON_F_LABEL,
- HWMON_F_INPUT | HWMON_F_LABEL,
- HWMON_F_INPUT | HWMON_F_LABEL
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET
),
HWMON_CHANNEL_INFO(pwm,
HWMON_PWM_INPUT,
@@ -348,7 +385,7 @@ static int get_fan_cnct(struct ccp_device *ccp)
int mode;
int ret;
- ret = send_usb_cmd(ccp, CTL_GET_FAN_CNCT, 0, 0);
+ ret = send_usb_cmd(ccp, CTL_GET_FAN_CNCT, 0, 0, 0);
if (ret)
return ret;
@@ -385,7 +422,7 @@ static int get_temp_cnct(struct ccp_device *ccp)
int mode;
int ret;
- ret = send_usb_cmd(ccp, CTL_GET_TMP_CNCT, 0, 0);
+ ret = send_usb_cmd(ccp, CTL_GET_TMP_CNCT, 0, 0, 0);
if (ret)
return ret;
--
2.27.0
On Thu, Jul 09, 2020 at 04:14:13PM +0200, Marius Zachmann wrote:
> This adds fan_target entries to the corsair-cpro driver.
> Reading the attribute from the device does not seem possible, so
> it returns the last set value. (same as pwm)
>
> send_usb_cmd now has one more argument, which is needed for the
> fan_target command.
>
> Signed-off-by: Marius Zachmann <[email protected]>
Applied.
Thanks,
Guenter
> ---
> Change from v1:
> - use clamp_val instead of bounds checking
>
> ---
> Documentation/hwmon/corsair-cpro.rst | 3 ++
> drivers/hwmon/corsair-cpro.c | 61 ++++++++++++++++++++++------
> 2 files changed, 52 insertions(+), 12 deletions(-)
>
> --
> 2.27.0
>
> diff --git a/Documentation/hwmon/corsair-cpro.rst b/Documentation/hwmon/corsair-cpro.rst
> index 5913e23d764c..78820156f07d 100644
> --- a/Documentation/hwmon/corsair-cpro.rst
> +++ b/Documentation/hwmon/corsair-cpro.rst
> @@ -33,6 +33,9 @@ in2_input Voltage on SATA 3.3v
> temp[1-4]_input Temperature on connected temperature sensors
> fan[1-6]_input Connected fan rpm.
> fan[1-6]_label Shows fan type as detected by the device.
> +fan[1-6]_target Sets fan speed target rpm.
> + When reading, it reports the last value if it was set by the driver.
> + Otherwise returns 0.
> pwm[1-6] Sets the fan speed. Values from 0-255.
> When reading, it reports the last value if it was set by the driver.
> Otherwise returns 0.
> diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c
> index a22583acc229..fe625190e3a1 100644
> --- a/drivers/hwmon/corsair-cpro.c
> +++ b/drivers/hwmon/corsair-cpro.c
> @@ -5,8 +5,8 @@
> */
>
> #include <linux/bitops.h>
> -#include <linux/kernel.h>
> #include <linux/hwmon.h>
> +#include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/mutex.h>
> #include <linux/slab.h>
> @@ -51,6 +51,12 @@
> * send: byte 1 is fan number
> * send: byte 2 is percentage from 0 - 100
> */
> +#define CTL_SET_FAN_TARGET 0x24 /*
> + * set target rpm
> + * send: byte 1 is fan number
> + * send: byte 2-3 is target
> + * device accepts all values from 0x00 - 0xFFFF
> + */
>
> #define NUM_FANS 6
> #define NUM_TEMP_SENSORS 4
> @@ -60,13 +66,14 @@ struct ccp_device {
> struct mutex mutex; /* whenever buffer is used, lock before send_usb_cmd */
> u8 *buffer;
> int pwm[6];
> + int target[6];
> DECLARE_BITMAP(temp_cnct, NUM_TEMP_SENSORS);
> DECLARE_BITMAP(fan_cnct, NUM_FANS);
> char fan_label[6][LABEL_LENGTH];
> };
>
> /* send command, check for error in response, response in ccp->buffer */
> -static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2)
> +static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2, u8 byte3)
> {
> int actual_length;
> int ret;
> @@ -75,6 +82,7 @@ static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2)
> ccp->buffer[0] = command;
> ccp->buffer[1] = byte1;
> ccp->buffer[2] = byte2;
> + ccp->buffer[3] = byte3;
>
> ret = usb_bulk_msg(ccp->udev, usb_sndintpipe(ccp->udev, 2), ccp->buffer, OUT_BUFFER_SIZE,
> &actual_length, 1000);
> @@ -103,7 +111,7 @@ static int get_data(struct ccp_device *ccp, int command, int channel)
>
> mutex_lock(&ccp->mutex);
>
> - ret = send_usb_cmd(ccp, command, channel, 0);
> + ret = send_usb_cmd(ccp, command, channel, 0, 0);
> if (ret)
> goto out_unlock;
>
> @@ -128,7 +136,22 @@ static int set_pwm(struct ccp_device *ccp, int channel, long val)
>
> mutex_lock(&ccp->mutex);
>
> - ret = send_usb_cmd(ccp, CTL_SET_FAN_FPWM, channel, val);
> + ret = send_usb_cmd(ccp, CTL_SET_FAN_FPWM, channel, val, 0);
> +
> + mutex_unlock(&ccp->mutex);
> + return ret;
> +}
> +
> +static int set_target(struct ccp_device *ccp, int channel, long val)
> +{
> + int ret;
> +
> + val = clamp_val(val, 0, 0xFFFF);
> + ccp->target[channel] = val;
> +
> + mutex_lock(&ccp->mutex);
> +
> + ret = send_usb_cmd(ccp, CTL_SET_FAN_TARGET, channel, val >> 8, val);
>
> mutex_unlock(&ccp->mutex);
> return ret;
> @@ -183,6 +206,11 @@ static int ccp_read(struct device *dev, enum hwmon_sensor_types type,
> return ret;
> *val = ret;
> return 0;
> + case hwmon_fan_target:
> + /* how to read target values from the device is unknown */
> + /* driver returns last set value or 0 */
> + *val = ccp->target[channel];
> + return 0;
> default:
> break;
> }
> @@ -231,6 +259,13 @@ static int ccp_write(struct device *dev, enum hwmon_sensor_types type,
> break;
> }
> break;
> + case hwmon_fan:
> + switch (attr) {
> + case hwmon_fan_target:
> + return set_target(ccp, channel, val);
> + default:
> + break;
> + }
> default:
> break;
> }
> @@ -266,6 +301,8 @@ static umode_t ccp_is_visible(const void *data, enum hwmon_sensor_types type,
> return 0444;
> case hwmon_fan_label:
> return 0444;
> + case hwmon_fan_target:
> + return 0644;
> default:
> break;
> }
> @@ -313,12 +350,12 @@ static const struct hwmon_channel_info *ccp_info[] = {
> HWMON_T_INPUT
> ),
> HWMON_CHANNEL_INFO(fan,
> - HWMON_F_INPUT | HWMON_F_LABEL,
> - HWMON_F_INPUT | HWMON_F_LABEL,
> - HWMON_F_INPUT | HWMON_F_LABEL,
> - HWMON_F_INPUT | HWMON_F_LABEL,
> - HWMON_F_INPUT | HWMON_F_LABEL,
> - HWMON_F_INPUT | HWMON_F_LABEL
> + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
> + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
> + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
> + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
> + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
> + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET
> ),
> HWMON_CHANNEL_INFO(pwm,
> HWMON_PWM_INPUT,
> @@ -348,7 +385,7 @@ static int get_fan_cnct(struct ccp_device *ccp)
> int mode;
> int ret;
>
> - ret = send_usb_cmd(ccp, CTL_GET_FAN_CNCT, 0, 0);
> + ret = send_usb_cmd(ccp, CTL_GET_FAN_CNCT, 0, 0, 0);
> if (ret)
> return ret;
>
> @@ -385,7 +422,7 @@ static int get_temp_cnct(struct ccp_device *ccp)
> int mode;
> int ret;
>
> - ret = send_usb_cmd(ccp, CTL_GET_TMP_CNCT, 0, 0);
> + ret = send_usb_cmd(ccp, CTL_GET_TMP_CNCT, 0, 0, 0);
> if (ret)
> return ret;