36
36
* send: byte 1 is channel, rest zero
37
37
* rcv: returns temp for channel in centi-degree celsius
38
38
* 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
40
40
*/
41
41
#define CTL_GET_VOLT 0x12 /*
42
42
* send: byte 1 is rail number: 0 = 12v, 1 = 5v, 2 = 3.3v
43
43
* rcv: returns millivolt in bytes 1,2
44
+ * returns error 0x10 if request is invalid
44
45
*/
45
46
#define CTL_GET_FAN_CNCT 0x20 /*
46
47
* returns in bytes 1-6 for each fan:
52
53
* send: byte 1 is channel, rest zero
53
54
* rcv: returns rpm in bytes 1,2
54
55
*/
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
+ */
55
62
#define CTL_SET_FAN_FPWM 0x23 /*
56
63
* set fixed pwm
57
64
* send: byte 1 is fan number
@@ -73,13 +80,31 @@ struct ccp_device {
73
80
struct completion wait_input_report ;
74
81
struct mutex mutex ; /* whenever buffer is used, lock before send_usb_cmd */
75
82
u8 * buffer ;
76
- int pwm [6 ];
77
83
int target [6 ];
78
84
DECLARE_BITMAP (temp_cnct , NUM_TEMP_SENSORS );
79
85
DECLARE_BITMAP (fan_cnct , NUM_FANS );
80
86
char fan_label [6 ][LABEL_LENGTH ];
81
87
};
82
88
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
+
83
108
/* send command, check for error in response, response in ccp->buffer */
84
109
static int send_usb_cmd (struct ccp_device * ccp , u8 command , u8 byte1 , u8 byte2 , u8 byte3 )
85
110
{
@@ -102,13 +127,7 @@ static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2,
102
127
if (!t )
103
128
return - ETIMEDOUT ;
104
129
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 );
112
131
}
113
132
114
133
static 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
126
145
}
127
146
128
147
/* 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 )
130
149
{
131
150
int ret ;
132
151
@@ -136,7 +155,9 @@ static int get_data(struct ccp_device *ccp, int command, int channel)
136
155
if (ret )
137
156
goto out_unlock ;
138
157
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 ];
140
161
141
162
out_unlock :
142
163
mutex_unlock (& ccp -> mutex );
@@ -150,14 +171,14 @@ static int set_pwm(struct ccp_device *ccp, int channel, long val)
150
171
if (val < 0 || val > 255 )
151
172
return - EINVAL ;
152
173
153
- ccp -> pwm [channel ] = val ;
154
-
155
174
/* The Corsair Commander Pro uses values from 0-100 */
156
175
val = DIV_ROUND_CLOSEST (val * 100 , 255 );
157
176
158
177
mutex_lock (& ccp -> mutex );
159
178
160
179
ret = send_usb_cmd (ccp , CTL_SET_FAN_FPWM , channel , val , 0 );
180
+ if (!ret )
181
+ ccp -> target [channel ] = - ENODATA ;
161
182
162
183
mutex_unlock (& ccp -> mutex );
163
184
return ret ;
@@ -171,7 +192,6 @@ static int set_target(struct ccp_device *ccp, int channel, long val)
171
192
ccp -> target [channel ] = val ;
172
193
173
194
mutex_lock (& ccp -> mutex );
174
-
175
195
ret = send_usb_cmd (ccp , CTL_SET_FAN_TARGET , channel , val >> 8 , val );
176
196
177
197
mutex_unlock (& ccp -> mutex );
@@ -210,7 +230,7 @@ static int ccp_read(struct device *dev, enum hwmon_sensor_types type,
210
230
case hwmon_temp :
211
231
switch (attr ) {
212
232
case hwmon_temp_input :
213
- ret = get_data (ccp , CTL_GET_TMP , channel );
233
+ ret = get_data (ccp , CTL_GET_TMP , channel , true );
214
234
if (ret < 0 )
215
235
return ret ;
216
236
* val = ret * 10 ;
@@ -222,14 +242,16 @@ static int ccp_read(struct device *dev, enum hwmon_sensor_types type,
222
242
case hwmon_fan :
223
243
switch (attr ) {
224
244
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 );
226
246
if (ret < 0 )
227
247
return ret ;
228
248
* val = ret ;
229
249
return 0 ;
230
250
case hwmon_fan_target :
231
251
/* how to read target values from the device is unknown */
232
252
/* driver returns last set value or 0 */
253
+ if (ccp -> target [channel ] < 0 )
254
+ return - ENODATA ;
233
255
* val = ccp -> target [channel ];
234
256
return 0 ;
235
257
default :
@@ -239,9 +261,10 @@ static int ccp_read(struct device *dev, enum hwmon_sensor_types type,
239
261
case hwmon_pwm :
240
262
switch (attr ) {
241
263
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 );
245
268
return 0 ;
246
269
default :
247
270
break ;
@@ -250,7 +273,7 @@ static int ccp_read(struct device *dev, enum hwmon_sensor_types type,
250
273
case hwmon_in :
251
274
switch (attr ) {
252
275
case hwmon_in_input :
253
- ret = get_data (ccp , CTL_GET_VOLT , channel );
276
+ ret = get_data (ccp , CTL_GET_VOLT , channel , true );
254
277
if (ret < 0 )
255
278
return ret ;
256
279
* val = ret ;
@@ -416,6 +439,7 @@ static int get_fan_cnct(struct ccp_device *ccp)
416
439
continue ;
417
440
418
441
set_bit (channel , ccp -> fan_cnct );
442
+ ccp -> target [channel ] = - ENODATA ;
419
443
420
444
switch (mode ) {
421
445
case 1 :
0 commit comments