1 /*
2 * This file is part of OpenCorsairLink.
3 * Copyright (C) 2017-2019 Sean Nelson <audiohacked@gmail.com>
4
5 * OpenCorsairLink is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * any later version.
9
10 * OpenCorsairLink is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14
15 * You should have received a copy of the GNU General Public License
16 * along with OpenCorsairLink. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "device.h"
20 #include "driver.h"
21 #include "lowlevel/asetek.h"
22 #include "print.h"
23 #include "protocol/asetekpro.h"
24
25 #include <errno.h>
26 #include <libusb.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31
32
33 int
corsairlink_asetekpro_fan_count(struct corsair_device_info * dev,struct libusb_device_handle * handle,struct fan_control * ctrl)34 corsairlink_asetekpro_fan_count(
35 struct corsair_device_info* dev, struct libusb_device_handle* handle, struct fan_control* ctrl )
36 {
37 int rr = 0;
38 // undefined, return device value from device.c
39 ctrl->fan_count = dev->fan_control_count;
40 return rr;
41 }
42
43 int
corsairlink_asetekpro_fan_print_mode(uint8_t mode,uint16_t data,char * modestr,uint8_t modestr_size)44 corsairlink_asetekpro_fan_print_mode(
45 uint8_t mode, uint16_t data, char* modestr, uint8_t modestr_size )
46 {
47 int rr = 0;
48 // undefined, return hex value of mode
49 snprintf( modestr, modestr_size, "Mode 0x%02X", mode );
50 return rr;
51 }
52
53 int
corsairlink_asetekpro_fan_mode(struct corsair_device_info * dev,struct libusb_device_handle * handle,struct fan_control * ctrl)54 corsairlink_asetekpro_fan_mode(
55 struct corsair_device_info* dev, struct libusb_device_handle* handle, struct fan_control* ctrl )
56 {
57 int rr;
58 if ( ctrl->mode == PERFORMANCE )
59 {
60 ASETEKPRO_FAN_TABLE_EXTREME( ctrl->table );
61 }
62 else if ( ctrl->mode == QUIET )
63 {
64 ASETEKPRO_FAN_TABLE_QUIET( ctrl->table );
65 }
66 rr = dev->driver->fan.profile.write_custom_curve( dev, handle, ctrl );
67
68 return rr;
69 }
70
71 int
corsairlink_asetekpro_fan_mode_read(struct corsair_device_info * dev,struct libusb_device_handle * handle,struct fan_control * ctrl)72 corsairlink_asetekpro_fan_mode_read(
73 struct corsair_device_info* dev, struct libusb_device_handle* handle, struct fan_control* ctrl )
74 {
75 int rr;
76 uint8_t response[64];
77 uint8_t commands[64];
78 memset( response, 0, sizeof( response ) );
79 memset( commands, 0, sizeof( commands ) );
80
81 commands[0] = 0x20;
82
83 rr = dev->driver->write( handle, dev->write_endpoint, commands, 32 );
84 rr = dev->driver->read( handle, dev->read_endpoint, response, 32 );
85
86 msg_debug2( "%02X\n", response[0x16] );
87 ctrl->mode = response[0x16];
88
89 return rr;
90 }
91
92 int
corsairlink_asetekpro_fan_mode_performance(struct corsair_device_info * dev,struct libusb_device_handle * handle,struct fan_control * ctrl)93 corsairlink_asetekpro_fan_mode_performance(
94 struct corsair_device_info* dev, struct libusb_device_handle* handle, struct fan_control* ctrl )
95 {
96 int rr;
97 ASETEKPRO_FAN_TABLE_EXTREME( ctrl->table );
98 rr = dev->driver->fan.profile.write_custom_curve( dev, handle, ctrl );
99
100 return rr;
101 }
102
103 int
corsairlink_asetekpro_fan_mode_balanced(struct corsair_device_info * dev,struct libusb_device_handle * handle,struct fan_control * ctrl)104 corsairlink_asetekpro_fan_mode_balanced(
105 struct corsair_device_info* dev, struct libusb_device_handle* handle, struct fan_control* ctrl )
106 {
107 int rr;
108 ASETEKPRO_FAN_TABLE_BALANCED( ctrl->table );
109 rr = dev->driver->fan.profile.write_custom_curve( dev, handle, ctrl );
110
111 return rr;
112 }
113
114 int
corsairlink_asetekpro_fan_mode_quiet(struct corsair_device_info * dev,struct libusb_device_handle * handle,struct fan_control * ctrl)115 corsairlink_asetekpro_fan_mode_quiet(
116 struct corsair_device_info* dev, struct libusb_device_handle* handle, struct fan_control* ctrl )
117 {
118 int rr;
119 ASETEKPRO_FAN_TABLE_QUIET( ctrl->table );
120 rr = dev->driver->fan.profile.write_custom_curve( dev, handle, ctrl );
121
122 return rr;
123 }
124
125 int
corsairlink_asetekpro_fan_curve(struct corsair_device_info * dev,struct libusb_device_handle * handle,struct fan_control * ctrl)126 corsairlink_asetekpro_fan_curve(
127 struct corsair_device_info* dev, struct libusb_device_handle* handle, struct fan_control* ctrl )
128 {
129 int rr;
130 uint8_t response[64];
131 uint8_t commands[64];
132 memset( response, 0, sizeof( response ) );
133 memset( commands, 0, sizeof( commands ) );
134
135 commands[0] = AsetekProFanWrite;
136 commands[1] = ctrl->channel;
137
138 commands[2] = ctrl->table[0].temperature;
139 commands[3] = ctrl->table[1].temperature;
140 commands[4] = ctrl->table[2].temperature;
141 commands[5] = ctrl->table[3].temperature;
142 commands[6] = ctrl->table[4].temperature;
143 commands[7] = ctrl->table[5].temperature;
144 commands[8] = ctrl->table[6].temperature;
145
146 commands[9] = ctrl->table[0].speed;
147 commands[10] = ctrl->table[1].speed;
148 commands[11] = ctrl->table[2].speed;
149 commands[12] = ctrl->table[3].speed;
150 commands[13] = ctrl->table[4].speed;
151 commands[14] = ctrl->table[5].speed;
152 commands[15] = ctrl->table[6].speed;
153
154
155 msg_debug2( "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X \n", commands[0], commands[1], commands[2], commands[3], commands[4], commands[5], commands[6], commands[7], commands[8], commands[9], commands[10], commands[11], commands[12], commands[13], commands[14], commands[15]);
156
157
158 rr = dev->driver->write( handle, dev->write_endpoint, commands, 16 );
159 rr = dev->driver->read( handle, dev->read_endpoint, response, 32 );
160
161 return rr;
162 }
163
164 int
corsairlink_asetekpro_fan_speed(struct corsair_device_info * dev,struct libusb_device_handle * handle,struct fan_control * ctrl)165 corsairlink_asetekpro_fan_speed(
166 struct corsair_device_info* dev, struct libusb_device_handle* handle, struct fan_control* ctrl )
167 {
168 int rr;
169 uint8_t response[64];
170 uint8_t commands[64];
171 memset( response, 0, sizeof( response ) );
172 memset( commands, 0, sizeof( commands ) );
173
174 commands[0] = AsetekProFanRead; // fan speed query
175 commands[1] = ctrl->channel; // fan port
176
177 rr = dev->driver->write( handle, dev->write_endpoint, commands, 2 );
178 rr = dev->driver->read( handle, dev->read_endpoint, response, 6 );
179
180 msg_debug2(
181 "%02X %02X %02X %02X %02X %02X\n", response[0], response[1], response[2], response[3],
182 response[4], response[5] );
183
184 if ( response[0] != 0x41 || response[1] != 0x12 || response[2] != 0x34
185 || response[3] != ctrl->channel )
186 {
187 msg_debug2( "Bad Response\n" );
188 }
189
190 ctrl->speed_rpm = ( response[4] << 8 ) + response[5];
191 ctrl->max_speed = 0;
192
193 return rr;
194 }
195
196
197 int
corsairlink_asetekpro_fan_mode_rpm(struct corsair_device_info * dev,struct libusb_device_handle * handle,struct fan_control * ctrl)198 corsairlink_asetekpro_fan_mode_rpm(
199 struct corsair_device_info* dev, struct libusb_device_handle* handle, struct fan_control* ctrl )
200 {
201 int rr;
202 uint8_t response[64];
203 uint8_t commands[64];
204 memset( response, 0, sizeof( response ) );
205 memset( commands, 0, sizeof( commands ) );
206
207 commands[0] = AsetekProFanFixedRPMWrite;
208 commands[1] = ctrl->channel;
209 commands[2] = ( ctrl->speed_rpm >> 8 );
210 commands[3] = ctrl->speed_rpm;
211
212 msg_debug2("%02X %02X %02X %02X\n", commands[0], commands[1], commands[2], commands[3]);
213
214 rr = dev->driver->write( handle, dev->write_endpoint, commands, 4 );
215 rr = dev->driver->read( handle, dev->read_endpoint, response, 64 );
216
217 return rr;
218 }
219
220 int
corsairlink_asetekpro_fan_mode_pwm(struct corsair_device_info * dev,struct libusb_device_handle * handle,struct fan_control * ctrl)221 corsairlink_asetekpro_fan_mode_pwm(
222 struct corsair_device_info* dev, struct libusb_device_handle* handle, struct fan_control* ctrl )
223 {
224 int rr;
225 uint8_t response[64];
226 uint8_t commands[64];
227 memset( response, 0, sizeof( response ) );
228 memset( commands, 0, sizeof( commands ) );
229
230 commands[0] = AsetekProFanFixedPWMWrite;
231 commands[1] = ctrl->channel;
232 commands[2] = ctrl->speed_pwm;
233
234 msg_debug2("%02X %02X %02X\n", commands[0], commands[1], commands[2]);
235
236 rr = dev->driver->write( handle, dev->write_endpoint, commands, 3 );
237 rr = dev->driver->read( handle, dev->read_endpoint, response, 32 );
238
239 return rr;
240 }