3636 * send: byte 1 is channel, rest zero
3737 * rcv: returns temp for channel in centi-degree celsius
3838 * in bytes 1 and 2
39- * returns 17 in byte 0 if no sensor is connected
39+ * returns 0x11 in byte 0 if no sensor is connected
4040 */
4141#define CTL_GET_VOLT 0x12 /*
4242 * send: byte 1 is rail number: 0 = 12v, 1 = 5v, 2 = 3.3v
4343 * rcv: returns millivolt in bytes 1,2
44+ * returns error 0x10 if request is invalid
4445 */
4546#define CTL_GET_FAN_CNCT 0x20 /*
4647 * returns in bytes 1-6 for each fan:
5253 * send: byte 1 is channel, rest zero
5354 * rcv: returns rpm in bytes 1,2
5455 */
56+ #define CTL_GET_FAN_PWM 0x22 /*
57+ * send: byte 1 is channel, rest zero
58+ * rcv: returns pwm in byte 1 if it was set
59+ * returns error 0x12 if fan is controlled via
60+ * fan_target or fan curve
61+ */
5562#define CTL_SET_FAN_FPWM 0x23 /*
5663 * set fixed pwm
5764 * send: byte 1 is fan number
@@ -73,13 +80,31 @@ struct ccp_device {
7380 struct completion wait_input_report ;
7481 struct mutex mutex ; /* whenever buffer is used, lock before send_usb_cmd */
7582 u8 * buffer ;
76- int pwm [6 ];
7783 int target [6 ];
7884 DECLARE_BITMAP (temp_cnct , NUM_TEMP_SENSORS );
7985 DECLARE_BITMAP (fan_cnct , NUM_FANS );
8086 char fan_label [6 ][LABEL_LENGTH ];
8187};
8288
89+ /* converts response error in buffer to errno */
90+ static int ccp_get_errno (struct ccp_device * ccp )
91+ {
92+ switch (ccp -> buffer [0 ]) {
93+ case 0x00 : /* success */
94+ return 0 ;
95+ case 0x01 : /* called invalid command */
96+ return - EOPNOTSUPP ;
97+ case 0x10 : /* called GET_VOLT / GET_TMP with invalid arguments */
98+ return - EINVAL ;
99+ case 0x11 : /* requested temps of disconnected sensors */
100+ case 0x12 : /* requested pwm of not pwm controlled channels */
101+ return - ENODATA ;
102+ default :
103+ hid_dbg (ccp -> hdev , "unknown device response error: %d" , ccp -> buffer [0 ]);
104+ return - EIO ;
105+ }
106+ }
107+
83108/* send command, check for error in response, response in ccp->buffer */
84109static int send_usb_cmd (struct ccp_device * ccp , u8 command , u8 byte1 , u8 byte2 , u8 byte3 )
85110{
@@ -102,13 +127,7 @@ static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2,
102127 if (!t )
103128 return - ETIMEDOUT ;
104129
105- /* first byte of response is error code */
106- if (ccp -> buffer [0 ] != 0x00 ) {
107- hid_dbg (ccp -> hdev , "device response error: %d" , ccp -> buffer [0 ]);
108- return - EIO ;
109- }
110-
111- return 0 ;
130+ return ccp_get_errno (ccp );
112131}
113132
114133static int ccp_raw_event (struct hid_device * hdev , struct hid_report * report , u8 * data , int size )
@@ -126,7 +145,7 @@ static int ccp_raw_event(struct hid_device *hdev, struct hid_report *report, u8
126145}
127146
128147/* requests and returns single data values depending on channel */
129- static int get_data (struct ccp_device * ccp , int command , int channel )
148+ static int get_data (struct ccp_device * ccp , int command , int channel , bool two_byte_data )
130149{
131150 int ret ;
132151
@@ -136,7 +155,9 @@ static int get_data(struct ccp_device *ccp, int command, int channel)
136155 if (ret )
137156 goto out_unlock ;
138157
139- ret = (ccp -> buffer [1 ] << 8 ) + ccp -> buffer [2 ];
158+ ret = ccp -> buffer [1 ];
159+ if (two_byte_data )
160+ ret = (ret << 8 ) + ccp -> buffer [2 ];
140161
141162out_unlock :
142163 mutex_unlock (& ccp -> mutex );
@@ -150,14 +171,14 @@ static int set_pwm(struct ccp_device *ccp, int channel, long val)
150171 if (val < 0 || val > 255 )
151172 return - EINVAL ;
152173
153- ccp -> pwm [channel ] = val ;
154-
155174 /* The Corsair Commander Pro uses values from 0-100 */
156175 val = DIV_ROUND_CLOSEST (val * 100 , 255 );
157176
158177 mutex_lock (& ccp -> mutex );
159178
160179 ret = send_usb_cmd (ccp , CTL_SET_FAN_FPWM , channel , val , 0 );
180+ if (!ret )
181+ ccp -> target [channel ] = - ENODATA ;
161182
162183 mutex_unlock (& ccp -> mutex );
163184 return ret ;
@@ -171,7 +192,6 @@ static int set_target(struct ccp_device *ccp, int channel, long val)
171192 ccp -> target [channel ] = val ;
172193
173194 mutex_lock (& ccp -> mutex );
174-
175195 ret = send_usb_cmd (ccp , CTL_SET_FAN_TARGET , channel , val >> 8 , val );
176196
177197 mutex_unlock (& ccp -> mutex );
@@ -210,7 +230,7 @@ static int ccp_read(struct device *dev, enum hwmon_sensor_types type,
210230 case hwmon_temp :
211231 switch (attr ) {
212232 case hwmon_temp_input :
213- ret = get_data (ccp , CTL_GET_TMP , channel );
233+ ret = get_data (ccp , CTL_GET_TMP , channel , true );
214234 if (ret < 0 )
215235 return ret ;
216236 * val = ret * 10 ;
@@ -222,14 +242,16 @@ static int ccp_read(struct device *dev, enum hwmon_sensor_types type,
222242 case hwmon_fan :
223243 switch (attr ) {
224244 case hwmon_fan_input :
225- ret = get_data (ccp , CTL_GET_FAN_RPM , channel );
245+ ret = get_data (ccp , CTL_GET_FAN_RPM , channel , true );
226246 if (ret < 0 )
227247 return ret ;
228248 * val = ret ;
229249 return 0 ;
230250 case hwmon_fan_target :
231251 /* how to read target values from the device is unknown */
232252 /* driver returns last set value or 0 */
253+ if (ccp -> target [channel ] < 0 )
254+ return - ENODATA ;
233255 * val = ccp -> target [channel ];
234256 return 0 ;
235257 default :
@@ -239,9 +261,10 @@ static int ccp_read(struct device *dev, enum hwmon_sensor_types type,
239261 case hwmon_pwm :
240262 switch (attr ) {
241263 case hwmon_pwm_input :
242- /* how to read pwm values from the device is currently unknown */
243- /* driver returns last set value or 0 */
244- * val = ccp -> pwm [channel ];
264+ ret = get_data (ccp , CTL_GET_FAN_PWM , channel , false);
265+ if (ret < 0 )
266+ return ret ;
267+ * val = DIV_ROUND_CLOSEST (ret * 255 , 100 );
245268 return 0 ;
246269 default :
247270 break ;
@@ -250,7 +273,7 @@ static int ccp_read(struct device *dev, enum hwmon_sensor_types type,
250273 case hwmon_in :
251274 switch (attr ) {
252275 case hwmon_in_input :
253- ret = get_data (ccp , CTL_GET_VOLT , channel );
276+ ret = get_data (ccp , CTL_GET_VOLT , channel , true );
254277 if (ret < 0 )
255278 return ret ;
256279 * val = ret ;
@@ -416,6 +439,7 @@ static int get_fan_cnct(struct ccp_device *ccp)
416439 continue ;
417440
418441 set_bit (channel , ccp -> fan_cnct );
442+ ccp -> target [channel ] = - ENODATA ;
419443
420444 switch (mode ) {
421445 case 1 :
0 commit comments