blob: 3f27298916d46aee2e732f6f54a673a27381dc0d [file] [log] [blame]
Urja Rannikko0870b022016-01-31 22:10:29 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2011 asbokid <ballymunboy@gmail.com>
5 * Copyright (C) 2014 Pluto Yang <yangyj.ee@gmail.com>
6 * Copyright (C) 2015-2016 Stefan Tauner
7 * Copyright (C) 2015 Urja Rannikko <urjaman@gmail.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
Urja Rannikko0870b022016-01-31 22:10:29 +000018 */
19
20#include <string.h>
21#include <libusb.h>
22#include "flash.h"
Miriam Polzer1cea5c32020-12-23 17:28:38 +010023#include "platform.h"
Urja Rannikko0870b022016-01-31 22:10:29 +000024#include "programmer.h"
25
26/* LIBUSB_CALL ensures the right calling conventions on libusb callbacks.
27 * However, the macro is not defined everywhere. m(
28 */
29#ifndef LIBUSB_CALL
30#define LIBUSB_CALL
31#endif
32
33#define USB_TIMEOUT 1000 /* 1000 ms is plenty and we have no backup strategy anyway. */
34#define WRITE_EP 0x02
35#define READ_EP 0x82
36
37#define CH341_PACKET_LENGTH 0x20
38#define CH341_MAX_PACKETS 256
39#define CH341_MAX_PACKET_LEN (CH341_PACKET_LENGTH * CH341_MAX_PACKETS)
40
41#define CH341A_CMD_SET_OUTPUT 0xA1
42#define CH341A_CMD_IO_ADDR 0xA2
43#define CH341A_CMD_PRINT_OUT 0xA3
44#define CH341A_CMD_SPI_STREAM 0xA8
45#define CH341A_CMD_SIO_STREAM 0xA9
46#define CH341A_CMD_I2C_STREAM 0xAA
47#define CH341A_CMD_UIO_STREAM 0xAB
48
49#define CH341A_CMD_I2C_STM_START 0x74
50#define CH341A_CMD_I2C_STM_STOP 0x75
51#define CH341A_CMD_I2C_STM_OUT 0x80
52#define CH341A_CMD_I2C_STM_IN 0xC0
53#define CH341A_CMD_I2C_STM_MAX ( min( 0x3F, CH341_PACKET_LENGTH ) )
54#define CH341A_CMD_I2C_STM_SET 0x60 // bit 2: SPI with two data pairs D5,D4=out, D7,D6=in
55#define CH341A_CMD_I2C_STM_US 0x40
56#define CH341A_CMD_I2C_STM_MS 0x50
57#define CH341A_CMD_I2C_STM_DLY 0x0F
58#define CH341A_CMD_I2C_STM_END 0x00
59
60#define CH341A_CMD_UIO_STM_IN 0x00
61#define CH341A_CMD_UIO_STM_DIR 0x40
62#define CH341A_CMD_UIO_STM_OUT 0x80
63#define CH341A_CMD_UIO_STM_US 0xC0
64#define CH341A_CMD_UIO_STM_END 0x20
65
66#define CH341A_STM_I2C_20K 0x00
67#define CH341A_STM_I2C_100K 0x01
68#define CH341A_STM_I2C_400K 0x02
69#define CH341A_STM_I2C_750K 0x03
70#define CH341A_STM_SPI_DBL 0x04
71
72
73/* Number of parallel IN transfers. 32 seems to produce the most stable throughput on Windows. */
74#define USB_IN_TRANSFERS 32
75
76/* We need to use many queued IN transfers for any resemblance of performance (especially on Windows)
77 * because USB spec says that transfers end on non-full packets and the device sends the 31 reply
78 * data bytes to each 32-byte packet with command + 31 bytes of data... */
79static struct libusb_transfer *transfer_out = NULL;
80static struct libusb_transfer *transfer_ins[USB_IN_TRANSFERS] = {0};
81
82/* Accumulate delays to be plucked between CS deassertion and CS assertions. */
83static unsigned int stored_delay_us = 0;
84
85static struct libusb_device_handle *handle = NULL;
86
Thomas Heijligencc853d82021-05-04 15:32:17 +020087static const struct dev_entry devs_ch341a_spi[] = {
Urja Rannikko0870b022016-01-31 22:10:29 +000088 {0x1A86, 0x5512, OK, "Winchiphead (WCH)", "CH341A"},
89
90 {0},
91};
92
93enum trans_state {TRANS_ACTIVE = -2, TRANS_ERR = -1, TRANS_IDLE = 0};
94
95static void print_hex(const void *buf, size_t len)
96{
97 size_t i;
98 for (i = 0; i < len; i++) {
99 msg_pspew(" %02x", ((uint8_t *)buf)[i]);
100 if (i % CH341_PACKET_LENGTH == CH341_PACKET_LENGTH - 1)
101 msg_pspew("\n");
102 }
103}
104
105static void cb_common(const char *func, struct libusb_transfer *transfer)
106{
107 int *transfer_cnt = (int*)transfer->user_data;
108
109 if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
110 /* Silently ACK and exit. */
111 *transfer_cnt = TRANS_IDLE;
112 return;
113 }
114
115 if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
116 msg_perr("\n%s: error: %s\n", func, libusb_error_name(transfer->status));
117 *transfer_cnt = TRANS_ERR;
118 } else {
119 *transfer_cnt = transfer->actual_length;
120 }
121}
122
123/* callback for bulk out async transfer */
124static void LIBUSB_CALL cb_out(struct libusb_transfer *transfer)
125{
126 cb_common(__func__, transfer);
127}
128
129/* callback for bulk in async transfer */
130static void LIBUSB_CALL cb_in(struct libusb_transfer *transfer)
131{
132 cb_common(__func__, transfer);
133}
134
135static int32_t usb_transfer(const char *func, unsigned int writecnt, unsigned int readcnt, const uint8_t *writearr, uint8_t *readarr)
136{
137 if (handle == NULL)
138 return -1;
139
140 int state_out = TRANS_IDLE;
141 transfer_out->buffer = (uint8_t*)writearr;
142 transfer_out->length = writecnt;
143 transfer_out->user_data = &state_out;
144
145 /* Schedule write first */
146 if (writecnt > 0) {
147 state_out = TRANS_ACTIVE;
148 int ret = libusb_submit_transfer(transfer_out);
149 if (ret) {
150 msg_perr("%s: failed to submit OUT transfer: %s\n", func, libusb_error_name(ret));
151 state_out = TRANS_ERR;
152 goto err;
153 }
154 }
155
156 /* Handle all asynchronous packets as long as we have stuff to write or read. The write(s) simply need
157 * to complete but we need to scheduling reads as long as we are not done. */
158 unsigned int free_idx = 0; /* The IN transfer we expect to be free next. */
159 unsigned int in_idx = 0; /* The IN transfer we expect to be completed next. */
160 unsigned int in_done = 0;
161 unsigned int in_active = 0;
162 unsigned int out_done = 0;
163 uint8_t *in_buf = readarr;
164 int state_in[USB_IN_TRANSFERS] = {0};
165 do {
166 /* Schedule new reads as long as there are free transfers and unscheduled bytes to read. */
167 while ((in_done + in_active) < readcnt && state_in[free_idx] == TRANS_IDLE) {
168 unsigned int cur_todo = min(CH341_PACKET_LENGTH - 1, readcnt - in_done - in_active);
169 transfer_ins[free_idx]->length = cur_todo;
170 transfer_ins[free_idx]->buffer = in_buf;
171 transfer_ins[free_idx]->user_data = &state_in[free_idx];
172 int ret = libusb_submit_transfer(transfer_ins[free_idx]);
173 if (ret) {
174 state_in[free_idx] = TRANS_ERR;
175 msg_perr("%s: failed to submit IN transfer: %s\n",
176 func, libusb_error_name(ret));
177 goto err;
178 }
179 in_buf += cur_todo;
180 in_active += cur_todo;
181 state_in[free_idx] = TRANS_ACTIVE;
182 free_idx = (free_idx + 1) % USB_IN_TRANSFERS; /* Increment (and wrap around). */
183 }
184
185 /* Actually get some work done. */
186 libusb_handle_events_timeout(NULL, &(struct timeval){1, 0});
187
188 /* Check for the write */
189 if (out_done < writecnt) {
190 if (state_out == TRANS_ERR) {
191 goto err;
192 } else if (state_out > 0) {
193 out_done += state_out;
194 state_out = TRANS_IDLE;
195 }
196 }
197 /* Check for completed transfers. */
198 while (state_in[in_idx] != TRANS_IDLE && state_in[in_idx] != TRANS_ACTIVE) {
199 if (state_in[in_idx] == TRANS_ERR) {
200 goto err;
201 }
202 /* If a transfer is done, record the number of bytes read and reuse it later. */
203 in_done += state_in[in_idx];
204 in_active -= state_in[in_idx];
205 state_in[in_idx] = TRANS_IDLE;
206 in_idx = (in_idx + 1) % USB_IN_TRANSFERS; /* Increment (and wrap around). */
207 }
208 } while ((out_done < writecnt) || (in_done < readcnt));
209
210 if (out_done > 0) {
211 msg_pspew("Wrote %d bytes:\n", out_done);
212 print_hex(writearr, out_done);
213 msg_pspew("\n\n");
214 }
215 if (in_done > 0) {
216 msg_pspew("Read %d bytes:\n", in_done);
217 print_hex(readarr, in_done);
218 msg_pspew("\n\n");
219 }
220 return 0;
221err:
222 /* Clean up on errors. */
223 msg_perr("%s: Failed to %s %d bytes\n", func, (state_out == TRANS_ERR) ? "write" : "read",
224 (state_out == TRANS_ERR) ? writecnt : readcnt);
225 /* First, we must cancel any ongoing requests and wait for them to be canceled. */
226 if ((writecnt > 0) && (state_out == TRANS_ACTIVE)) {
227 if (libusb_cancel_transfer(transfer_out) != 0)
228 state_out = TRANS_ERR;
229 }
230 if (readcnt > 0) {
231 unsigned int i;
232 for (i = 0; i < USB_IN_TRANSFERS; i++) {
233 if (state_in[i] == TRANS_ACTIVE)
234 if (libusb_cancel_transfer(transfer_ins[i]) != 0)
235 state_in[i] = TRANS_ERR;
236 }
237 }
238
239 /* Wait for cancellations to complete. */
240 while (1) {
241 bool finished = true;
242 if ((writecnt > 0) && (state_out == TRANS_ACTIVE))
243 finished = false;
244 if (readcnt > 0) {
245 unsigned int i;
246 for (i = 0; i < USB_IN_TRANSFERS; i++) {
247 if (state_in[i] == TRANS_ACTIVE)
248 finished = false;
249 }
250 }
251 if (finished)
252 break;
253 libusb_handle_events_timeout(NULL, &(struct timeval){1, 0});
254 }
255 return -1;
256}
257
258/* Set the I2C bus speed (speed(b1b0): 0 = 20kHz; 1 = 100kHz, 2 = 400kHz, 3 = 750kHz).
259 * Set the SPI bus data width (speed(b2): 0 = Single, 1 = Double). */
260static int32_t config_stream(uint32_t speed)
261{
262 if (handle == NULL)
263 return -1;
264
265 uint8_t buf[] = {
266 CH341A_CMD_I2C_STREAM,
267 CH341A_CMD_I2C_STM_SET | (speed & 0x7),
268 CH341A_CMD_I2C_STM_END
269 };
270
271 int32_t ret = usb_transfer(__func__, sizeof(buf), 0, buf, NULL);
272 if (ret < 0) {
273 msg_perr("Could not configure stream interface.\n");
274 }
275 return ret;
276}
277
Urja Rannikko0870b022016-01-31 22:10:29 +0000278/* The assumed map between UIO command bits, pins on CH341A chip and pins on SPI chip:
279 * UIO CH341A SPI CH341A SPI name
Elyes HAOUASac01baa2018-05-28 16:52:21 +0200280 * 0 D0/15 CS/1 (CS0)
Urja Rannikko0870b022016-01-31 22:10:29 +0000281 * 1 D1/16 unused (CS1)
282 * 2 D2/17 unused (CS2)
283 * 3 D3/18 SCK/6 (DCK)
284 * 4 D4/19 unused (DOUT2)
285 * 5 D5/20 SI/5 (DOUT)
286 * - The UIO stream commands seem to only have 6 bits of output, and D6/D7 are the SPI inputs,
287 * mapped as follows:
288 * D6/21 unused (DIN2)
289 * D7/22 SO/2 (DIN)
290 */
291static int32_t enable_pins(bool enable)
292{
293 uint8_t buf[] = {
294 CH341A_CMD_UIO_STREAM,
295 CH341A_CMD_UIO_STM_OUT | 0x37, // CS high (all of them), SCK=0, DOUT*=1
296 CH341A_CMD_UIO_STM_DIR | (enable ? 0x3F : 0x00), // Interface output enable / disable
297 CH341A_CMD_UIO_STM_END,
298 };
299
300 int32_t ret = usb_transfer(__func__, sizeof(buf), 0, buf, NULL);
301 if (ret < 0) {
302 msg_perr("Could not %sable output pins.\n", enable ? "en" : "dis");
303 }
304 return ret;
305}
306
307/* De-assert and assert CS in one operation. */
308static void pluck_cs(uint8_t *ptr)
309{
Elyes HAOUASe2c90c42018-08-18 09:04:41 +0200310 /* This was measured to give a minimum deassertion time of 2.25 us,
Urja Rannikko0870b022016-01-31 22:10:29 +0000311 * >20x more than needed for most SPI chips (100ns). */
312 int delay_cnt = 2;
313 if (stored_delay_us) {
314 delay_cnt = (stored_delay_us * 4) / 3;
315 stored_delay_us = 0;
316 }
317 *ptr++ = CH341A_CMD_UIO_STREAM;
318 *ptr++ = CH341A_CMD_UIO_STM_OUT | 0x37; /* deasserted */
319 int i;
320 for (i = 0; i < delay_cnt; i++)
321 *ptr++ = CH341A_CMD_UIO_STM_OUT | 0x37; /* "delay" */
322 *ptr++ = CH341A_CMD_UIO_STM_OUT | 0x36; /* asserted */
323 *ptr++ = CH341A_CMD_UIO_STM_END;
324}
325
Thomas Heijligencc853d82021-05-04 15:32:17 +0200326static void ch341a_spi_delay(unsigned int usecs)
Urja Rannikko0870b022016-01-31 22:10:29 +0000327{
328 /* There is space for 28 bytes instructions of 750 ns each in the CS packet (32 - 4 for the actual CS
329 * instructions), thus max 21 us, but we avoid getting too near to this boundary and use
330 * internal_delay() for durations over 20 us. */
331 if ((usecs + stored_delay_us) > 20) {
332 unsigned int inc = 20 - stored_delay_us;
333 internal_delay(usecs - inc);
334 usecs = inc;
335 }
336 stored_delay_us += usecs;
337}
338
Edward O'Callaghan5eca4272020-04-12 17:27:53 +1000339static int ch341a_spi_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr)
Urja Rannikko0870b022016-01-31 22:10:29 +0000340{
341 if (handle == NULL)
342 return -1;
343
344 /* How many packets ... */
345 const size_t packets = (writecnt + readcnt + CH341_PACKET_LENGTH - 2) / (CH341_PACKET_LENGTH - 1);
346
347 /* We pluck CS/timeout handling into the first packet thus we need to allocate one extra package. */
348 uint8_t wbuf[packets+1][CH341_PACKET_LENGTH];
349 uint8_t rbuf[writecnt + readcnt];
350 /* Initialize the write buffer to zero to prevent writing random stack contents to device. */
351 memset(wbuf[0], 0, CH341_PACKET_LENGTH);
352
353 uint8_t *ptr = wbuf[0];
354 /* CS usage is optimized by doing both transitions in one packet.
355 * Final transition to deselected state is in the pin disable. */
356 pluck_cs(ptr);
357 unsigned int write_left = writecnt;
358 unsigned int read_left = readcnt;
359 unsigned int p;
360 for (p = 0; p < packets; p++) {
361 unsigned int write_now = min(CH341_PACKET_LENGTH - 1, write_left);
362 unsigned int read_now = min ((CH341_PACKET_LENGTH - 1) - write_now, read_left);
363 ptr = wbuf[p+1];
364 *ptr++ = CH341A_CMD_SPI_STREAM;
365 unsigned int i;
366 for (i = 0; i < write_now; ++i)
Marc Schink7ecfe482016-03-17 16:07:23 +0100367 *ptr++ = reverse_byte(*writearr++);
Urja Rannikko0870b022016-01-31 22:10:29 +0000368 if (read_now) {
369 memset(ptr, 0xFF, read_now);
370 read_left -= read_now;
371 }
372 write_left -= write_now;
373 }
374
375 int32_t ret = usb_transfer(__func__, CH341_PACKET_LENGTH + packets + writecnt + readcnt,
376 writecnt + readcnt, wbuf[0], rbuf);
377 if (ret < 0)
378 return -1;
379
380 unsigned int i;
381 for (i = 0; i < readcnt; i++) {
Marc Schink7ecfe482016-03-17 16:07:23 +0100382 *readarr++ = reverse_byte(rbuf[writecnt + i]);
Urja Rannikko0870b022016-01-31 22:10:29 +0000383 }
384
385 return 0;
386}
387
Anastasia Klimchukc63d9182021-07-06 16:18:44 +1000388static int ch341a_spi_shutdown(void *data);
389
Urja Rannikko0870b022016-01-31 22:10:29 +0000390static const struct spi_master spi_master_ch341a_spi = {
Nico Huber1cf407b2017-11-10 20:18:23 +0100391 .features = SPI_MASTER_4BA,
Martin Rothf6c1cb12022-03-15 10:55:25 -0600392 /* flashrom's current maximum is 256 B. CH341A was tested on Linux and Windows to accept at least
Urja Rannikko0870b022016-01-31 22:10:29 +0000393 * 128 kB. Basically there should be no hard limit because transfers are broken up into USB packets
394 * sent to the device and most of their payload streamed via SPI. */
395 .max_data_read = 4 * 1024,
396 .max_data_write = 4 * 1024,
397 .command = ch341a_spi_spi_send_command,
398 .multicommand = default_spi_send_multicommand,
399 .read = default_spi_read,
400 .write_256 = default_spi_write_256,
401 .write_aai = default_spi_write_aai,
Anastasia Klimchukc63d9182021-07-06 16:18:44 +1000402 .shutdown = ch341a_spi_shutdown,
Urja Rannikko0870b022016-01-31 22:10:29 +0000403};
404
405static int ch341a_spi_shutdown(void *data)
406{
407 if (handle == NULL)
408 return -1;
409
410 enable_pins(false);
411 libusb_free_transfer(transfer_out);
412 transfer_out = NULL;
413 int i;
414 for (i = 0; i < USB_IN_TRANSFERS; i++) {
415 libusb_free_transfer(transfer_ins[i]);
416 transfer_ins[i] = NULL;
417 }
418 libusb_release_interface(handle, 0);
419 libusb_close(handle);
420 libusb_exit(NULL);
421 handle = NULL;
422 return 0;
423}
424
Thomas Heijligencc853d82021-05-04 15:32:17 +0200425static int ch341a_spi_init(void)
Urja Rannikko0870b022016-01-31 22:10:29 +0000426{
427 if (handle != NULL) {
Nico Huberac90af62022-12-18 00:22:47 +0000428 msg_cerr("%s: handle already set! Please report a bug at flashrom-stable@flashrom.org\n",
429 __func__);
Urja Rannikko0870b022016-01-31 22:10:29 +0000430 return -1;
431 }
432
433 int32_t ret = libusb_init(NULL);
434 if (ret < 0) {
Martin Rothf6c1cb12022-03-15 10:55:25 -0600435 msg_perr("Couldn't initialize libusb!\n");
Urja Rannikko0870b022016-01-31 22:10:29 +0000436 return -1;
437 }
438
Alex James291764a2018-04-14 22:59:57 -0500439 /* Enable information, warning, and error messages (only). */
440#if LIBUSB_API_VERSION < 0x01000106
441 libusb_set_debug(NULL, 3);
442#else
443 libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
444#endif
Urja Rannikko0870b022016-01-31 22:10:29 +0000445
446 uint16_t vid = devs_ch341a_spi[0].vendor_id;
447 uint16_t pid = devs_ch341a_spi[0].device_id;
448 handle = libusb_open_device_with_vid_pid(NULL, vid, pid);
449 if (handle == NULL) {
450 msg_perr("Couldn't open device %04x:%04x.\n", vid, pid);
451 return -1;
452 }
453
454/* libusb_detach_kernel_driver() and friends basically only work on Linux. We simply try to detach on Linux
455 * without a lot of passion here. If that works fine else we will fail on claiming the interface anyway. */
456#if IS_LINUX
457 ret = libusb_detach_kernel_driver(handle, 0);
458 if (ret == LIBUSB_ERROR_NOT_SUPPORTED) {
459 msg_pwarn("Detaching kernel drivers is not supported. Further accesses may fail.\n");
460 } else if (ret != 0 && ret != LIBUSB_ERROR_NOT_FOUND) {
461 msg_pwarn("Failed to detach kernel driver: '%s'. Further accesses will probably fail.\n",
462 libusb_error_name(ret));
463 }
464#endif
465
466 ret = libusb_claim_interface(handle, 0);
467 if (ret != 0) {
468 msg_perr("Failed to claim interface 0: '%s'\n", libusb_error_name(ret));
469 goto close_handle;
470 }
471
472 struct libusb_device *dev;
473 if (!(dev = libusb_get_device(handle))) {
474 msg_perr("Failed to get device from device handle.\n");
475 goto close_handle;
476 }
477
478 struct libusb_device_descriptor desc;
479 ret = libusb_get_device_descriptor(dev, &desc);
480 if (ret < 0) {
481 msg_perr("Failed to get device descriptor: '%s'\n", libusb_error_name(ret));
482 goto release_interface;
483 }
484
485 msg_pdbg("Device revision is %d.%01d.%01d\n",
486 (desc.bcdDevice >> 8) & 0x00FF,
487 (desc.bcdDevice >> 4) & 0x000F,
488 (desc.bcdDevice >> 0) & 0x000F);
489
490 /* Allocate and pre-fill transfer structures. */
491 transfer_out = libusb_alloc_transfer(0);
492 if (!transfer_out) {
493 msg_perr("Failed to alloc libusb OUT transfer\n");
494 goto release_interface;
495 }
496 int i;
497 for (i = 0; i < USB_IN_TRANSFERS; i++) {
498 transfer_ins[i] = libusb_alloc_transfer(0);
499 if (transfer_ins[i] == NULL) {
500 msg_perr("Failed to alloc libusb IN transfer %d\n", i);
501 goto dealloc_transfers;
502 }
503 }
504 /* We use these helpers but dont fill the actual buffer yet. */
505 libusb_fill_bulk_transfer(transfer_out, handle, WRITE_EP, NULL, 0, cb_out, NULL, USB_TIMEOUT);
506 for (i = 0; i < USB_IN_TRANSFERS; i++)
507 libusb_fill_bulk_transfer(transfer_ins[i], handle, READ_EP, NULL, 0, cb_in, NULL, USB_TIMEOUT);
508
509 if ((config_stream(CH341A_STM_I2C_100K) < 0) || (enable_pins(true) < 0))
510 goto dealloc_transfers;
511
Anastasia Klimchukc63d9182021-07-06 16:18:44 +1000512 return register_spi_master(&spi_master_ch341a_spi, NULL);
Urja Rannikko0870b022016-01-31 22:10:29 +0000513
514dealloc_transfers:
515 for (i = 0; i < USB_IN_TRANSFERS; i++) {
516 if (transfer_ins[i] == NULL)
517 break;
518 libusb_free_transfer(transfer_ins[i]);
519 transfer_ins[i] = NULL;
520 }
521 libusb_free_transfer(transfer_out);
522 transfer_out = NULL;
523release_interface:
524 libusb_release_interface(handle, 0);
525close_handle:
526 libusb_close(handle);
527 handle = NULL;
528 return -1;
529}
Thomas Heijligencc853d82021-05-04 15:32:17 +0200530
531const struct programmer_entry programmer_ch341a_spi = {
532 .name = "ch341a_spi",
533 .type = USB,
534 .devs.dev = devs_ch341a_spi,
535 .init = ch341a_spi_init,
536 .map_flash_region = fallback_map,
537 .unmap_flash_region = fallback_unmap,
538 .delay = ch341a_spi_delay,
539};