blob: 91ef7a5b9a93e0e51f5c4ac4a08672ffe49da13b [file] [log] [blame]
Jon West7d881402021-04-15 08:42:42 -04001/*
2 * Copyright (c) 2015 Tim Theede <pez2001@voyagerproject.de>
3 * 2015 Terry Cain <terry@terrys-home.co.uk>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 */
10#include <linux/kernel.h>
11#include <linux/slab.h>
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/hid.h>
15
16
17#include "razercommon.h"
18
19/**
20 * Send USB control report to the keyboard
21 * USUALLY index = 0x02
22 * FIREFLY is 0
23 */
24int razer_send_control_msg(struct usb_device *usb_dev,void const *data, uint report_index, ulong wait_min, ulong wait_max)
25{
26 uint request = HID_REQ_SET_REPORT; // 0x09
27 uint request_type = USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT; // 0x21
28 uint value = 0x300;
29 uint size = RAZER_USB_REPORT_LEN;
30 char *buf;
31 int len;
32
33 buf = kmemdup(data, size, GFP_KERNEL);
34 if (buf == NULL)
35 return -ENOMEM;
36
37 // Send usb control message
38 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
39 request, // Request
40 request_type, // RequestType
41 value, // Value
42 report_index, // Index
43 buf, // Data
44 size, // Length
45 USB_CTRL_SET_TIMEOUT);
46
47 // Wait
48 usleep_range(wait_min, wait_max);
49
50 kfree(buf);
51 if(len!=size)
52 printk(KERN_WARNING "razer driver: Device data transfer failed.");
53
54 return ((len < 0) ? len : ((len != size) ? -EIO : 0));
55}
56
57/**
58 * Get a response from the razer device
59 *
60 * Makes a request like normal, this must change a variable in the device as then we
61 * tell it give us data and it gives us a report.
62 *
63 * Supported Devices:
64 * Razer Chroma
65 * Razer Mamba
66 * Razer BlackWidow Ultimate 2013*
67 * Razer Firefly*
68 *
69 * Request report is the report sent to the device specifying what response we want
70 * Response report will get populated with a response
71 *
72 * Returns 0 when successful, 1 if the report length is invalid.
73 */
74int razer_get_usb_response(struct usb_device *usb_dev, uint report_index, struct razer_report* request_report, uint response_index, struct razer_report* response_report, ulong wait_min, ulong wait_max)
75{
76 uint request = HID_REQ_GET_REPORT; // 0x01
77 uint request_type = USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN; // 0xA1
78 uint value = 0x300;
79
80 uint size = RAZER_USB_REPORT_LEN; // 0x90
81 int len;
82 int retval;
83 int result = 0;
84 char *buf;
85
86 buf = kzalloc(sizeof(struct razer_report), GFP_KERNEL);
87 if (buf == NULL)
88 return -ENOMEM;
89
90 // Send the request to the device.
91 // TODO look to see if index needs to be different for the request and the response
92 retval = razer_send_control_msg(usb_dev, request_report, report_index, wait_min, wait_max);
93
94 // Now ask for response
95 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
96 request, // Request
97 request_type, // RequestType
98 value, // Value
99 response_index, // Index
100 buf, // Data
101 size,
102 USB_CTRL_SET_TIMEOUT);
103
104 memcpy(response_report, buf, sizeof(struct razer_report));
105 kfree(buf);
106
107 // Error if report is wrong length
108 if(len != 90) {
109 printk(KERN_WARNING "razer driver: Invalid USB response. USB Report length: %d\n", len);
110 result = 1;
111 }
112
113 return result;
114}
115
116/**
117 * Calculate the checksum for the usb message
118 *
119 * Checksum byte is stored in the 2nd last byte in the messages payload.
120 * The checksum is generated by XORing all the bytes in the report starting
121 * at byte number 2 (0 based) and ending at byte 88.
122 */
123unsigned char razer_calculate_crc(struct razer_report *report)
124{
125 /*second to last byte of report is a simple checksum*/
126 /*just xor all bytes up with overflow and you are done*/
127 unsigned char crc = 0;
128 unsigned char *_report = (unsigned char*)report;
129
130 unsigned int i;
131 for(i = 2; i < 88; i++) {
132 crc ^= _report[i];
133 }
134
135 return crc;
136}
137
138/**
139 * Get initialised razer report
140 */
141struct razer_report get_razer_report(unsigned char command_class, unsigned char command_id, unsigned char data_size)
142{
143 struct razer_report new_report = {0};
144 memset(&new_report, 0, sizeof(struct razer_report));
145
146 new_report.status = 0x00;
147 new_report.transaction_id.id = 0xFF;
148 new_report.remaining_packets = 0x00;
149 new_report.protocol_type = 0x00;
150 new_report.command_class = command_class;
151 new_report.command_id.id = command_id;
152 new_report.data_size = data_size;
153
154 return new_report;
155}
156
157/**
158 * Get empty razer report
159 */
160struct razer_report get_empty_razer_report(void)
161{
162 struct razer_report new_report = {0};
163 memset(&new_report, 0, sizeof(struct razer_report));
164
165 return new_report;
166}
167
168/**
169 * Print report to syslog
170 */
171void print_erroneous_report(struct razer_report* report, char* driver_name, char* message)
172{
173 printk(KERN_WARNING "%s: %s. Start Marker: %02x id: %02x Num Params: %02x Reserved: %02x Command: %02x Params: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x .\n",
174 driver_name,
175 message,
176 report->status,
177 report->transaction_id.id,
178 report->data_size,
179 report->command_class,
180 report->command_id.id,
181 report->arguments[0], report->arguments[1], report->arguments[2], report->arguments[3], report->arguments[4], report->arguments[5],
182 report->arguments[6], report->arguments[7], report->arguments[8], report->arguments[9], report->arguments[10], report->arguments[11],
183 report->arguments[12], report->arguments[13], report->arguments[14], report->arguments[15]);
184}
185
186/**
187 * Clamp a value to a min,max
188 */
189unsigned char clamp_u8(unsigned char value, unsigned char min, unsigned char max)
190{
191 if(value > max)
192 return max;
193 if(value < min)
194 return min;
195 return value;
196}
197unsigned short clamp_u16(unsigned short value, unsigned short min, unsigned short max)
198{
199 if(value > max)
200 return max;
201 if(value < min)
202 return min;
203 return value;
204}
205
206
207int razer_send_control_msg_old_device(struct usb_device *usb_dev,void const *data, uint report_value, uint report_index, uint report_size, ulong wait_min, ulong wait_max)
208{
209 uint request = HID_REQ_SET_REPORT; // 0x09
210 uint request_type = USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT; // 0x21
211 char *buf;
212 int len;
213
214 buf = kmemdup(data, report_size, GFP_KERNEL);
215 if (buf == NULL)
216 return -ENOMEM;
217
218 // Send usb control message
219 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
220 request, // Request
221 request_type, // RequestType
222 report_value, // Value
223 report_index, // Index
224 buf, // Data
225 report_size, // Length
226 USB_CTRL_SET_TIMEOUT);
227
228 // Wait
229 usleep_range(wait_min, wait_max);
230
231 kfree(buf);
232 if(len!=report_size)
233 printk(KERN_WARNING "razer driver: Device data transfer failed.");
234
235 return ((len < 0) ? len : ((len != report_size) ? -EIO : 0));
236}
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252