GNU Linux-libre 5.4.257-gnu1
[releases.git] / sound / usb / 6fire / firmware.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Linux driver for TerraTec DMX 6Fire USB
4  *
5  * Firmware loader
6  *
7  * Author:      Torsten Schenk <torsten.schenk@zoho.com>
8  * Created:     Jan 01, 2011
9  * Copyright:   (C) Torsten Schenk
10  */
11
12 #include <linux/firmware.h>
13 #include <linux/module.h>
14 #include <linux/bitrev.h>
15 #include <linux/kernel.h>
16
17 #include "firmware.h"
18 #include "chip.h"
19
20 /*(DEBLOBBED)*/
21
22 enum {
23         FPGA_BUFSIZE = 512, FPGA_EP = 2
24 };
25
26 /*
27  * wMaxPacketSize of pcm endpoints.
28  * keep synced with rates_in_packet_size and rates_out_packet_size in pcm.c
29  * fpp: frames per isopacket
30  *
31  * CAUTION: keep sizeof <= buffer[] in usb6fire_fw_init
32  */
33 static const u8 ep_w_max_packet_size[] = {
34         0xe4, 0x00, 0xe4, 0x00, /* alt 1: 228 EP2 and EP6 (7 fpp) */
35         0xa4, 0x01, 0xa4, 0x01, /* alt 2: 420 EP2 and EP6 (13 fpp)*/
36         0x94, 0x01, 0x5c, 0x02  /* alt 3: 404 EP2 and 604 EP6 (25 fpp) */
37 };
38
39 static const u8 known_fw_versions[][2] = {
40         { 0x03, 0x01 }
41 };
42
43 struct ihex_record {
44         u16 address;
45         u8 len;
46         u8 data[256];
47         char error; /* true if an error occurred parsing this record */
48
49         u8 max_len; /* maximum record length in whole ihex */
50
51         /* private */
52         const char *txt_data;
53         unsigned int txt_length;
54         unsigned int txt_offset; /* current position in txt_data */
55 };
56
57 static u8 usb6fire_fw_ihex_hex(const u8 *data, u8 *crc)
58 {
59         u8 val = 0;
60         int hval;
61
62         hval = hex_to_bin(data[0]);
63         if (hval >= 0)
64                 val |= (hval << 4);
65
66         hval = hex_to_bin(data[1]);
67         if (hval >= 0)
68                 val |= hval;
69
70         *crc += val;
71         return val;
72 }
73
74 /*
75  * returns true if record is available, false otherwise.
76  * iff an error occurred, false will be returned and record->error will be true.
77  */
78 static bool usb6fire_fw_ihex_next_record(struct ihex_record *record)
79 {
80         u8 crc = 0;
81         u8 type;
82         int i;
83
84         record->error = false;
85
86         /* find begin of record (marked by a colon) */
87         while (record->txt_offset < record->txt_length
88                         && record->txt_data[record->txt_offset] != ':')
89                 record->txt_offset++;
90         if (record->txt_offset == record->txt_length)
91                 return false;
92
93         /* number of characters needed for len, addr and type entries */
94         record->txt_offset++;
95         if (record->txt_offset + 8 > record->txt_length) {
96                 record->error = true;
97                 return false;
98         }
99
100         record->len = usb6fire_fw_ihex_hex(record->txt_data +
101                         record->txt_offset, &crc);
102         record->txt_offset += 2;
103         record->address = usb6fire_fw_ihex_hex(record->txt_data +
104                         record->txt_offset, &crc) << 8;
105         record->txt_offset += 2;
106         record->address |= usb6fire_fw_ihex_hex(record->txt_data +
107                         record->txt_offset, &crc);
108         record->txt_offset += 2;
109         type = usb6fire_fw_ihex_hex(record->txt_data +
110                         record->txt_offset, &crc);
111         record->txt_offset += 2;
112
113         /* number of characters needed for data and crc entries */
114         if (record->txt_offset + 2 * (record->len + 1) > record->txt_length) {
115                 record->error = true;
116                 return false;
117         }
118         for (i = 0; i < record->len; i++) {
119                 record->data[i] = usb6fire_fw_ihex_hex(record->txt_data
120                                 + record->txt_offset, &crc);
121                 record->txt_offset += 2;
122         }
123         usb6fire_fw_ihex_hex(record->txt_data + record->txt_offset, &crc);
124         if (crc) {
125                 record->error = true;
126                 return false;
127         }
128
129         if (type == 1 || !record->len) /* eof */
130                 return false;
131         else if (type == 0)
132                 return true;
133         else {
134                 record->error = true;
135                 return false;
136         }
137 }
138
139 static int usb6fire_fw_ihex_init(const struct firmware *fw,
140                 struct ihex_record *record)
141 {
142         record->txt_data = fw->data;
143         record->txt_length = fw->size;
144         record->txt_offset = 0;
145         record->max_len = 0;
146         /* read all records, if loop ends, record->error indicates,
147          * whether ihex is valid. */
148         while (usb6fire_fw_ihex_next_record(record))
149                 record->max_len = max(record->len, record->max_len);
150         if (record->error)
151                 return -EINVAL;
152         record->txt_offset = 0;
153         return 0;
154 }
155
156 static int usb6fire_fw_ezusb_write(struct usb_device *device,
157                 int type, int value, char *data, int len)
158 {
159         int ret;
160
161         ret = usb_control_msg(device, usb_sndctrlpipe(device, 0), type,
162                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
163                         value, 0, data, len, 1000);
164         if (ret < 0)
165                 return ret;
166         else if (ret != len)
167                 return -EIO;
168         return 0;
169 }
170
171 static int usb6fire_fw_ezusb_read(struct usb_device *device,
172                 int type, int value, char *data, int len)
173 {
174         int ret = usb_control_msg(device, usb_rcvctrlpipe(device, 0), type,
175                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value,
176                         0, data, len, 1000);
177         if (ret < 0)
178                 return ret;
179         else if (ret != len)
180                 return -EIO;
181         return 0;
182 }
183
184 static int usb6fire_fw_fpga_write(struct usb_device *device,
185                 char *data, int len)
186 {
187         int actual_len;
188         int ret;
189
190         ret = usb_bulk_msg(device, usb_sndbulkpipe(device, FPGA_EP), data, len,
191                         &actual_len, 1000);
192         if (ret < 0)
193                 return ret;
194         else if (actual_len != len)
195                 return -EIO;
196         return 0;
197 }
198
199 static int usb6fire_fw_ezusb_upload(
200                 struct usb_interface *intf, const char *fwname,
201                 unsigned int postaddr, u8 *postdata, unsigned int postlen)
202 {
203         int ret;
204         u8 data;
205         struct usb_device *device = interface_to_usbdev(intf);
206         const struct firmware *fw = NULL;
207         struct ihex_record *rec = kmalloc(sizeof(struct ihex_record),
208                         GFP_KERNEL);
209
210         if (!rec)
211                 return -ENOMEM;
212
213         ret = reject_firmware(&fw, fwname, &device->dev);
214         if (ret < 0) {
215                 kfree(rec);
216                 dev_err(&intf->dev,
217                         "error requesting ezusb firmware %s.\n", fwname);
218                 return ret;
219         }
220         ret = usb6fire_fw_ihex_init(fw, rec);
221         if (ret < 0) {
222                 kfree(rec);
223                 release_firmware(fw);
224                 dev_err(&intf->dev,
225                         "error validating ezusb firmware %s.\n", fwname);
226                 return ret;
227         }
228         /* upload firmware image */
229         data = 0x01; /* stop ezusb cpu */
230         ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1);
231         if (ret < 0) {
232                 kfree(rec);
233                 release_firmware(fw);
234                 dev_err(&intf->dev,
235                         "unable to upload ezusb firmware %s: begin message.\n",
236                         fwname);
237                 return ret;
238         }
239
240         while (usb6fire_fw_ihex_next_record(rec)) { /* write firmware */
241                 ret = usb6fire_fw_ezusb_write(device, 0xa0, rec->address,
242                                 rec->data, rec->len);
243                 if (ret < 0) {
244                         kfree(rec);
245                         release_firmware(fw);
246                         dev_err(&intf->dev,
247                                 "unable to upload ezusb firmware %s: data urb.\n",
248                                 fwname);
249                         return ret;
250                 }
251         }
252
253         release_firmware(fw);
254         kfree(rec);
255         if (postdata) { /* write data after firmware has been uploaded */
256                 ret = usb6fire_fw_ezusb_write(device, 0xa0, postaddr,
257                                 postdata, postlen);
258                 if (ret < 0) {
259                         dev_err(&intf->dev,
260                                 "unable to upload ezusb firmware %s: post urb.\n",
261                                 fwname);
262                         return ret;
263                 }
264         }
265
266         data = 0x00; /* resume ezusb cpu */
267         ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1);
268         if (ret < 0) {
269                 dev_err(&intf->dev,
270                         "unable to upload ezusb firmware %s: end message.\n",
271                         fwname);
272                 return ret;
273         }
274         return 0;
275 }
276
277 static int usb6fire_fw_fpga_upload(
278                 struct usb_interface *intf, const char *fwname)
279 {
280         int ret;
281         int i;
282         struct usb_device *device = interface_to_usbdev(intf);
283         u8 *buffer = kmalloc(FPGA_BUFSIZE, GFP_KERNEL);
284         const char *c;
285         const char *end;
286         const struct firmware *fw;
287
288         if (!buffer)
289                 return -ENOMEM;
290
291         ret = reject_firmware(&fw, fwname, &device->dev);
292         if (ret < 0) {
293                 dev_err(&intf->dev, "unable to get fpga firmware %s.\n",
294                                 fwname);
295                 kfree(buffer);
296                 return -EIO;
297         }
298
299         c = fw->data;
300         end = fw->data + fw->size;
301
302         ret = usb6fire_fw_ezusb_write(device, 8, 0, NULL, 0);
303         if (ret < 0) {
304                 kfree(buffer);
305                 release_firmware(fw);
306                 dev_err(&intf->dev,
307                         "unable to upload fpga firmware: begin urb.\n");
308                 return ret;
309         }
310
311         while (c != end) {
312                 for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++)
313                         buffer[i] = bitrev8((u8)*c);
314
315                 ret = usb6fire_fw_fpga_write(device, buffer, i);
316                 if (ret < 0) {
317                         release_firmware(fw);
318                         kfree(buffer);
319                         dev_err(&intf->dev,
320                                 "unable to upload fpga firmware: fw urb.\n");
321                         return ret;
322                 }
323         }
324         release_firmware(fw);
325         kfree(buffer);
326
327         ret = usb6fire_fw_ezusb_write(device, 9, 0, NULL, 0);
328         if (ret < 0) {
329                 dev_err(&intf->dev,
330                         "unable to upload fpga firmware: end urb.\n");
331                 return ret;
332         }
333         return 0;
334 }
335
336 /* check, if the firmware version the devices has currently loaded
337  * is known by this driver. 'version' needs to have 4 bytes version
338  * info data. */
339 static int usb6fire_fw_check(struct usb_interface *intf, const u8 *version)
340 {
341         int i;
342
343         for (i = 0; i < ARRAY_SIZE(known_fw_versions); i++)
344                 if (!memcmp(version, known_fw_versions + i, 2))
345                         return 0;
346
347         dev_err(&intf->dev, "invalid firmware version in device: %4ph. "
348                         "please reconnect to power. if this failure "
349                         "still happens, check your firmware installation.",
350                         version);
351         return -EINVAL;
352 }
353
354 int usb6fire_fw_init(struct usb_interface *intf)
355 {
356         int i;
357         int ret;
358         struct usb_device *device = interface_to_usbdev(intf);
359         /* buffer: 8 receiving bytes from device and
360          * sizeof(EP_W_MAX_PACKET_SIZE) bytes for non-const copy */
361         u8 buffer[12];
362
363         ret = usb6fire_fw_ezusb_read(device, 1, 0, buffer, 8);
364         if (ret < 0) {
365                 dev_err(&intf->dev,
366                         "unable to receive device firmware state.\n");
367                 return ret;
368         }
369         if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55) {
370                 dev_err(&intf->dev,
371                         "unknown device firmware state received from device:");
372                 for (i = 0; i < 8; i++)
373                         printk(KERN_CONT "%02x ", buffer[i]);
374                 printk(KERN_CONT "\n");
375                 return -EIO;
376         }
377         /* do we need fpga loader ezusb firmware? */
378         if (buffer[3] == 0x01) {
379                 ret = usb6fire_fw_ezusb_upload(intf,
380                                 "/*(DEBLOBBED)*/", 0, NULL, 0);
381                 if (ret < 0)
382                         return ret;
383                 return FW_NOT_READY;
384         }
385         /* do we need fpga firmware and application ezusb firmware? */
386         else if (buffer[3] == 0x02) {
387                 ret = usb6fire_fw_check(intf, buffer + 4);
388                 if (ret < 0)
389                         return ret;
390                 ret = usb6fire_fw_fpga_upload(intf, "/*(DEBLOBBED)*/");
391                 if (ret < 0)
392                         return ret;
393                 memcpy(buffer, ep_w_max_packet_size,
394                                 sizeof(ep_w_max_packet_size));
395                 ret = usb6fire_fw_ezusb_upload(intf, "/*(DEBLOBBED)*/",
396                                 0x0003, buffer, sizeof(ep_w_max_packet_size));
397                 if (ret < 0)
398                         return ret;
399                 return FW_NOT_READY;
400         }
401         /* all fw loaded? */
402         else if (buffer[3] == 0x03)
403                 return usb6fire_fw_check(intf, buffer + 4);
404         /* unknown data? */
405         else {
406                 dev_err(&intf->dev,
407                         "unknown device firmware state received from device: ");
408                 for (i = 0; i < 8; i++)
409                         printk(KERN_CONT "%02x ", buffer[i]);
410                 printk(KERN_CONT "\n");
411                 return -EIO;
412         }
413         return 0;
414 }
415