blob: 55e08b9a490724c7f69607f69277e2984a322c0b [file] [log] [blame]
Nicholas Chin197b7c72022-10-23 13:10:31 -06001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2022 Nicholas Chin <nic.c3.14@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <string.h>
18#include <stdlib.h>
19#include <libusb.h>
20#include "platform.h"
21#include "programmer.h"
22#include "flash.h"
23
24#define CH347_CMD_SPI_SET_CFG 0xC0
25#define CH347_CMD_SPI_CS_CTRL 0xC1
26#define CH347_CMD_SPI_OUT_IN 0xC2
27#define CH347_CMD_SPI_IN 0xC3
28#define CH347_CMD_SPI_OUT 0xC4
29#define CH347_CMD_SPI_GET_CFG 0xCA
30
31#define CH347_CS_ASSERT 0x00
32#define CH347_CS_DEASSERT 0x40
33#define CH347_CS_CHANGE 0x80
34#define CH347_CS_IGNORE 0x00
35
36#define WRITE_EP 0x06
37#define READ_EP 0x86
38
39#define MODE_1_IFACE 2
40#define MODE_2_IFACE 1
41
42/* The USB descriptor says the max transfer size is 512 bytes, but the
43 * vendor driver only seems to transfer a maximum of 510 bytes at once,
44 * leaving 507 bytes for data as the command + length take up 3 bytes
45 */
46#define CH347_PACKET_SIZE 510
47#define CH347_MAX_DATA_LEN (CH347_PACKET_SIZE - 3)
48
49struct ch347_spi_data {
50 struct libusb_device_handle *handle;
51};
52
53/* TODO: Add support for HID mode */
54static const struct dev_entry devs_ch347_spi[] = {
55 {0x1A86, 0x55DB, OK, "QinHeng Electronics", "USB To UART+SPI+I2C"},
56 {0}
57};
58
59static int ch347_spi_shutdown(void *data)
60{
61 struct ch347_spi_data *ch347_data = data;
62
63 /* TODO: Set this depending on the mode */
64 int spi_interface = MODE_1_IFACE;
65 libusb_release_interface(ch347_data->handle, spi_interface);
66 libusb_attach_kernel_driver(ch347_data->handle, spi_interface);
67 libusb_close(ch347_data->handle);
68 libusb_exit(NULL);
69
70 free(data);
71 return 0;
72}
73
74static int ch347_cs_control(struct ch347_spi_data *ch347_data, uint8_t cs1, uint8_t cs2)
75{
76 uint8_t cmd[13] = {
77 [0] = CH347_CMD_SPI_CS_CTRL,
78 /* payload length, uint16 LSB: 10 */
79 [1] = 10,
80 [3] = cs1,
81 [8] = cs2
82 };
83
84 int32_t ret = libusb_bulk_transfer(ch347_data->handle, WRITE_EP, cmd, sizeof(cmd), NULL, 1000);
85 if (ret < 0) {
86 msg_perr("Could not change CS!\n");
87 return -1;
88 }
89 return 0;
90}
91
92
93static int ch347_write(struct ch347_spi_data *ch347_data, unsigned int writecnt, const uint8_t *writearr)
94{
95 unsigned int data_len;
96 int packet_len;
97 int transferred;
98 int ret;
99 uint8_t resp_buf[4] = {0};
100 uint8_t buffer[CH347_PACKET_SIZE] = {0};
101 unsigned int bytes_written = 0;
102
103 while (bytes_written < writecnt) {
104 data_len = min(CH347_MAX_DATA_LEN, writecnt - bytes_written );
105 packet_len = data_len + 3;
106
107 buffer[0] = CH347_CMD_SPI_OUT;
108 buffer[1] = (data_len) & 0xFF;
109 buffer[2] = ((data_len) & 0xFF00) >> 8;
110 memcpy(buffer + 3, writearr + bytes_written, data_len);
111
112 ret = libusb_bulk_transfer(ch347_data->handle, WRITE_EP, buffer, packet_len, &transferred, 1000);
113 if (ret < 0 || transferred != packet_len) {
114 msg_perr("Could not send write command\n");
115 return -1;
116 }
117
118 ret = libusb_bulk_transfer(ch347_data->handle, READ_EP, resp_buf, sizeof(resp_buf), NULL, 1000);
119 if (ret < 0) {
120 msg_perr("Could not receive write command response\n");
121 return -1;
122 }
123 bytes_written += data_len;
124 }
125 return 0;
126}
127
128static int ch347_read(struct ch347_spi_data *ch347_data, unsigned int readcnt, uint8_t *readarr)
129{
130 uint8_t *read_ptr = readarr;
131 int ret;
132 int transferred;
133 unsigned int bytes_read = 0;
134 uint8_t buffer[CH347_PACKET_SIZE] = {0};
135 uint8_t command_buf[7] = {
136 [0] = CH347_CMD_SPI_IN,
137 [1] = 4,
138 [2] = 0,
139 [3] = readcnt & 0xFF,
140 [4] = (readcnt & 0xFF00) >> 8,
141 [5] = (readcnt & 0xFF0000) >> 16,
142 [6] = (readcnt & 0xFF000000) >> 24
143 };
144
145 ret = libusb_bulk_transfer(ch347_data->handle, WRITE_EP, command_buf, sizeof(command_buf), &transferred, 1000);
146 if (ret < 0 || transferred != sizeof(command_buf)) {
147 msg_perr("Could not send read command\n");
148 return -1;
149 }
150
151 while (bytes_read < readcnt) {
152 ret = libusb_bulk_transfer(ch347_data->handle, READ_EP, buffer, CH347_PACKET_SIZE, &transferred, 1000);
153 if (ret < 0) {
154 msg_perr("Could not read data\n");
155 return -1;
156 }
157 if (transferred > CH347_PACKET_SIZE) {
158 msg_perr("libusb bug: bytes received overflowed buffer\n");
159 return -1;
160 }
161 /* Response: u8 command, u16 data length, then the data that was read */
162 if (transferred < 3) {
163 msg_perr("CH347 returned an invalid response to read command\n");
164 return -1;
165 }
166 int ch347_data_length = read_le16(buffer, 1);
167 if (transferred - 3 < ch347_data_length) {
168 msg_perr("CH347 returned less data than data length header indicates\n");
169 return -1;
170 }
171 bytes_read += ch347_data_length;
172 if (bytes_read > readcnt) {
173 msg_perr("CH347 returned more bytes than requested\n");
174 return -1;
175 }
176 memcpy(read_ptr, buffer + 3, ch347_data_length);
177 read_ptr += ch347_data_length;
178 }
179 return 0;
180}
181
182static int ch347_spi_send_command(const struct flashctx *flash, unsigned int writecnt,
183 unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr)
184{
185 struct ch347_spi_data *ch347_data = flash->mst->spi.data;
186 int ret = 0;
187
188 ch347_cs_control(ch347_data, CH347_CS_ASSERT | CH347_CS_CHANGE, CH347_CS_IGNORE);
189 if (writecnt) {
190 ret = ch347_write(ch347_data, writecnt, writearr);
191 if (ret < 0) {
192 msg_perr("CH347 write error\n");
193 return -1;
194 }
195 }
196 if (readcnt) {
197 ret = ch347_read(ch347_data, readcnt, readarr);
198 if (ret < 0) {
199 msg_perr("CH347 read error\n");
200 return -1;
201 }
202 }
203 ch347_cs_control(ch347_data, CH347_CS_DEASSERT | CH347_CS_CHANGE, CH347_CS_IGNORE);
204
205 return 0;
206}
207
208static int32_t ch347_spi_config(struct ch347_spi_data *ch347_data, uint8_t divisor)
209{
210 int32_t ret;
211 uint8_t buff[29] = {
212 [0] = CH347_CMD_SPI_SET_CFG,
213 [1] = (sizeof(buff) - 3) & 0xFF,
214 [2] = ((sizeof(buff) - 3) & 0xFF00) >> 8,
215 /* Not sure what these two bytes do, but the vendor
216 * drivers seem to unconditionally set these values
217 */
218 [5] = 4,
219 [6] = 1,
220 /* Clock polarity: bit 1 */
221 [9] = 0,
222 /* Clock phase: bit 0 */
223 [11] = 0,
224 /* Another mystery byte */
225 [14] = 2,
226 /* Clock divisor: bits 5:3 */
227 [15] = (divisor & 0x7) << 3,
228 /* Bit order: bit 7, 0=MSB */
229 [17] = 0,
230 /* Yet another mystery byte */
231 [19] = 7,
232 /* CS polarity: bit 7 CS2, bit 6 CS1. 0 = active low */
233 [24] = 0
234 };
235
236 ret = libusb_bulk_transfer(ch347_data->handle, WRITE_EP, buff, sizeof(buff), NULL, 1000);
237 if (ret < 0) {
238 msg_perr("Could not configure SPI interface\n");
239 }
240
241 /* FIXME: Not sure if the CH347 sends error responses for
242 * invalid config data, if so the code should check
243 */
244 ret = libusb_bulk_transfer(ch347_data->handle, READ_EP, buff, sizeof(buff), NULL, 1000);
245 if (ret < 0) {
246 msg_perr("Could not receive configure SPI command response\n");
247 }
248 return ret;
249}
250
251static const struct spi_master spi_master_ch347_spi = {
252 .features = SPI_MASTER_4BA,
253 .max_data_read = MAX_DATA_READ_UNLIMITED,
254 .max_data_write = MAX_DATA_WRITE_UNLIMITED,
255 .command = ch347_spi_send_command,
256 .multicommand = default_spi_send_multicommand,
257 .read = default_spi_read,
258 .write_256 = default_spi_write_256,
259 .write_aai = default_spi_write_aai,
260 .shutdown = ch347_spi_shutdown,
261 .probe_opcode = default_spi_probe_opcode,
262};
263
264/* Largely copied from ch341a_spi.c */
265static int ch347_spi_init(void)
266{
267 struct ch347_spi_data *ch347_data = calloc(1, sizeof(*ch347_data));
268 if (!ch347_data) {
269 msg_perr("Could not allocate space for SPI data\n");
270 return 1;
271 }
272
273 int32_t ret = libusb_init(NULL);
274 if (ret < 0) {
275 msg_perr("Could not initialize libusb!\n");
276 free(ch347_data);
277 return 1;
278 }
279
280 /* Enable information, warning, and error messages (only). */
281#if LIBUSB_API_VERSION < 0x01000106
282 libusb_set_debug(NULL, 3);
283#else
284 libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
285#endif
286
287 uint16_t vid = devs_ch347_spi[0].vendor_id;
288 uint16_t pid = devs_ch347_spi[0].device_id;
289 ch347_data->handle = libusb_open_device_with_vid_pid(NULL, vid, pid);
290 if (ch347_data->handle == NULL) {
291 msg_perr("Couldn't open device %04x:%04x.\n", vid, pid);
292 free(ch347_data);
293 return 1;
294 }
295
296 /* TODO: set based on mode */
297 /* Mode 1 uses interface 2 for the SPI interface */
298 int spi_interface = MODE_1_IFACE;
299
300 ret = libusb_detach_kernel_driver(ch347_data->handle, spi_interface);
301 if (ret != 0 && ret != LIBUSB_ERROR_NOT_FOUND)
302 msg_pwarn("Cannot detach the existing USB driver. Claiming the interface may fail. %s\n",
303 libusb_error_name(ret));
304
305 ret = libusb_claim_interface(ch347_data->handle, spi_interface);
306 if (ret != 0) {
307 msg_perr("Failed to claim interface 2: '%s'\n", libusb_error_name(ret));
308 goto error_exit;
309 }
310
311 struct libusb_device *dev;
312 if (!(dev = libusb_get_device(ch347_data->handle))) {
313 msg_perr("Failed to get device from device handle.\n");
314 goto error_exit;
315 }
316
317 struct libusb_device_descriptor desc;
318 ret = libusb_get_device_descriptor(dev, &desc);
319 if (ret < 0) {
320 msg_perr("Failed to get device descriptor: '%s'\n", libusb_error_name(ret));
321 goto error_exit;
322 }
323
324 msg_pdbg("Device revision is %d.%01d.%01d\n",
325 (desc.bcdDevice >> 8) & 0x00FF,
326 (desc.bcdDevice >> 4) & 0x000F,
327 (desc.bcdDevice >> 0) & 0x000F);
328
329 /* TODO: add programmer cfg for things like CS pin and divisor */
330 if (ch347_spi_config(ch347_data, 2) < 0)
331 goto error_exit;
332
333 return register_spi_master(&spi_master_ch347_spi, ch347_data);
334
335error_exit:
336 ch347_spi_shutdown(ch347_data);
337 return 1;
338}
339
340const struct programmer_entry programmer_ch347_spi = {
341 .name = "ch347_spi",
342 .type = USB,
343 .devs.dev = devs_ch347_spi,
344 .init = ch347_spi_init,
345};