1*0d6140beSAndroid Build Coastguard Worker /*
2*0d6140beSAndroid Build Coastguard Worker * This file is part of the flashrom project.
3*0d6140beSAndroid Build Coastguard Worker *
4*0d6140beSAndroid Build Coastguard Worker * Copyright 2022 Alexander Goncharov <[email protected]>
5*0d6140beSAndroid Build Coastguard Worker *
6*0d6140beSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify
7*0d6140beSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
8*0d6140beSAndroid Build Coastguard Worker * the Free Software Foundation; version 2 of the License.
9*0d6140beSAndroid Build Coastguard Worker *
10*0d6140beSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
11*0d6140beSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*0d6140beSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*0d6140beSAndroid Build Coastguard Worker * GNU General Public License for more details.
14*0d6140beSAndroid Build Coastguard Worker */
15*0d6140beSAndroid Build Coastguard Worker
16*0d6140beSAndroid Build Coastguard Worker #include "lifecycle.h"
17*0d6140beSAndroid Build Coastguard Worker
18*0d6140beSAndroid Build Coastguard Worker #if CONFIG_CH341A_SPI == 1
19*0d6140beSAndroid Build Coastguard Worker
20*0d6140beSAndroid Build Coastguard Worker /* Same macro as in ch341a_spi.c programmer. */
21*0d6140beSAndroid Build Coastguard Worker #define WRITE_EP 0x02
22*0d6140beSAndroid Build Coastguard Worker #define READ_EP 0x82
23*0d6140beSAndroid Build Coastguard Worker
24*0d6140beSAndroid Build Coastguard Worker struct ch341a_spi_io_state {
25*0d6140beSAndroid Build Coastguard Worker struct libusb_transfer *transfer_out;
26*0d6140beSAndroid Build Coastguard Worker /*
27*0d6140beSAndroid Build Coastguard Worker * Since the test transfers a data that fits in one CH341 packet, we
28*0d6140beSAndroid Build Coastguard Worker * don't need an array of these transfers (as is done in the driver code).
29*0d6140beSAndroid Build Coastguard Worker */
30*0d6140beSAndroid Build Coastguard Worker struct libusb_transfer *transfer_in;
31*0d6140beSAndroid Build Coastguard Worker };
32*0d6140beSAndroid Build Coastguard Worker
ch341a_libusb_alloc_transfer(void * state,int iso_packets)33*0d6140beSAndroid Build Coastguard Worker static struct libusb_transfer *ch341a_libusb_alloc_transfer(void *state, int iso_packets)
34*0d6140beSAndroid Build Coastguard Worker {
35*0d6140beSAndroid Build Coastguard Worker return calloc(1, sizeof(struct libusb_transfer));
36*0d6140beSAndroid Build Coastguard Worker }
37*0d6140beSAndroid Build Coastguard Worker
38*0d6140beSAndroid Build Coastguard Worker /*
39*0d6140beSAndroid Build Coastguard Worker * The libusb code stores submitted transfers in their own context. But this
40*0d6140beSAndroid Build Coastguard Worker * function doesn't require a context pointer because libusb stores context
41*0d6140beSAndroid Build Coastguard Worker * pointers in libusb_transfer instances. Since our ch341 driver is using
42*0d6140beSAndroid Build Coastguard Worker * the default context, we store the transfer in our own.
43*0d6140beSAndroid Build Coastguard Worker */
ch341a_libusb_submit_transfer(void * state,struct libusb_transfer * transfer)44*0d6140beSAndroid Build Coastguard Worker static int ch341a_libusb_submit_transfer(void *state, struct libusb_transfer *transfer)
45*0d6140beSAndroid Build Coastguard Worker {
46*0d6140beSAndroid Build Coastguard Worker struct ch341a_spi_io_state *io_state = state;
47*0d6140beSAndroid Build Coastguard Worker
48*0d6140beSAndroid Build Coastguard Worker assert_true(transfer->endpoint == WRITE_EP || transfer->endpoint == READ_EP);
49*0d6140beSAndroid Build Coastguard Worker
50*0d6140beSAndroid Build Coastguard Worker if (transfer->endpoint == WRITE_EP) {
51*0d6140beSAndroid Build Coastguard Worker assert_null(io_state->transfer_out);
52*0d6140beSAndroid Build Coastguard Worker io_state->transfer_out = transfer;
53*0d6140beSAndroid Build Coastguard Worker } else if (transfer->endpoint == READ_EP) {
54*0d6140beSAndroid Build Coastguard Worker assert_null(io_state->transfer_in);
55*0d6140beSAndroid Build Coastguard Worker io_state->transfer_in = transfer;
56*0d6140beSAndroid Build Coastguard Worker }
57*0d6140beSAndroid Build Coastguard Worker
58*0d6140beSAndroid Build Coastguard Worker return 0;
59*0d6140beSAndroid Build Coastguard Worker }
60*0d6140beSAndroid Build Coastguard Worker
ch341a_libusb_free_transfer(void * state,struct libusb_transfer * transfer)61*0d6140beSAndroid Build Coastguard Worker static void ch341a_libusb_free_transfer(void *state, struct libusb_transfer *transfer)
62*0d6140beSAndroid Build Coastguard Worker {
63*0d6140beSAndroid Build Coastguard Worker free(transfer);
64*0d6140beSAndroid Build Coastguard Worker }
65*0d6140beSAndroid Build Coastguard Worker
66*0d6140beSAndroid Build Coastguard Worker /*
67*0d6140beSAndroid Build Coastguard Worker * Handle submitted transfers by pretending that a transfer is completed and
68*0d6140beSAndroid Build Coastguard Worker * invoking its callback (that is the flashrom code).
69*0d6140beSAndroid Build Coastguard Worker */
ch341a_libusb_handle_events_timeout(void * state,libusb_context * ctx,struct timeval * tv)70*0d6140beSAndroid Build Coastguard Worker static int ch341a_libusb_handle_events_timeout(void *state, libusb_context *ctx, struct timeval *tv)
71*0d6140beSAndroid Build Coastguard Worker {
72*0d6140beSAndroid Build Coastguard Worker struct ch341a_spi_io_state *io_state = state;
73*0d6140beSAndroid Build Coastguard Worker
74*0d6140beSAndroid Build Coastguard Worker if (io_state->transfer_out) {
75*0d6140beSAndroid Build Coastguard Worker io_state->transfer_out->status = LIBUSB_TRANSFER_COMPLETED;
76*0d6140beSAndroid Build Coastguard Worker io_state->transfer_out->actual_length = io_state->transfer_out->length;
77*0d6140beSAndroid Build Coastguard Worker io_state->transfer_out->callback(io_state->transfer_out);
78*0d6140beSAndroid Build Coastguard Worker io_state->transfer_out = NULL;
79*0d6140beSAndroid Build Coastguard Worker }
80*0d6140beSAndroid Build Coastguard Worker
81*0d6140beSAndroid Build Coastguard Worker if (io_state->transfer_in) {
82*0d6140beSAndroid Build Coastguard Worker io_state->transfer_in->buffer[1] = reverse_byte(0xEF); /* WINBOND_NEX_ID */
83*0d6140beSAndroid Build Coastguard Worker io_state->transfer_in->buffer[2] = reverse_byte(0x40); /* WINBOND_NEX_W25Q128_V left byte */
84*0d6140beSAndroid Build Coastguard Worker io_state->transfer_in->buffer[3] = reverse_byte(0x18); /* WINBOND_NEX_W25Q128_V right byte */
85*0d6140beSAndroid Build Coastguard Worker
86*0d6140beSAndroid Build Coastguard Worker io_state->transfer_in->status = LIBUSB_TRANSFER_COMPLETED;
87*0d6140beSAndroid Build Coastguard Worker io_state->transfer_in->actual_length = io_state->transfer_in->length;
88*0d6140beSAndroid Build Coastguard Worker io_state->transfer_in->callback(io_state->transfer_in);
89*0d6140beSAndroid Build Coastguard Worker io_state->transfer_in = NULL;
90*0d6140beSAndroid Build Coastguard Worker }
91*0d6140beSAndroid Build Coastguard Worker
92*0d6140beSAndroid Build Coastguard Worker return 0;
93*0d6140beSAndroid Build Coastguard Worker }
94*0d6140beSAndroid Build Coastguard Worker
ch341a_spi_basic_lifecycle_test_success(void ** state)95*0d6140beSAndroid Build Coastguard Worker void ch341a_spi_basic_lifecycle_test_success(void **state)
96*0d6140beSAndroid Build Coastguard Worker {
97*0d6140beSAndroid Build Coastguard Worker struct ch341a_spi_io_state ch341a_spi_io_state = { 0 };
98*0d6140beSAndroid Build Coastguard Worker struct io_mock_fallback_open_state ch341a_spi_fallback_open_state = {
99*0d6140beSAndroid Build Coastguard Worker .noc = 0,
100*0d6140beSAndroid Build Coastguard Worker .paths = { LOCK_FILE },
101*0d6140beSAndroid Build Coastguard Worker };
102*0d6140beSAndroid Build Coastguard Worker const struct io_mock ch341a_spi_io = {
103*0d6140beSAndroid Build Coastguard Worker .state = &ch341a_spi_io_state,
104*0d6140beSAndroid Build Coastguard Worker .libusb_alloc_transfer = &ch341a_libusb_alloc_transfer,
105*0d6140beSAndroid Build Coastguard Worker .libusb_submit_transfer = &ch341a_libusb_submit_transfer,
106*0d6140beSAndroid Build Coastguard Worker .libusb_free_transfer = &ch341a_libusb_free_transfer,
107*0d6140beSAndroid Build Coastguard Worker .libusb_handle_events_timeout = &ch341a_libusb_handle_events_timeout,
108*0d6140beSAndroid Build Coastguard Worker .fallback_open_state = &ch341a_spi_fallback_open_state,
109*0d6140beSAndroid Build Coastguard Worker };
110*0d6140beSAndroid Build Coastguard Worker
111*0d6140beSAndroid Build Coastguard Worker run_basic_lifecycle(state, &ch341a_spi_io, &programmer_ch341a_spi, "");
112*0d6140beSAndroid Build Coastguard Worker }
113*0d6140beSAndroid Build Coastguard Worker
ch341a_spi_probe_lifecycle_test_success(void ** state)114*0d6140beSAndroid Build Coastguard Worker void ch341a_spi_probe_lifecycle_test_success(void **state)
115*0d6140beSAndroid Build Coastguard Worker {
116*0d6140beSAndroid Build Coastguard Worker struct ch341a_spi_io_state ch341a_spi_io_state = { 0 };
117*0d6140beSAndroid Build Coastguard Worker struct io_mock_fallback_open_state ch341a_spi_fallback_open_state = {
118*0d6140beSAndroid Build Coastguard Worker .noc = 0,
119*0d6140beSAndroid Build Coastguard Worker .paths = { LOCK_FILE },
120*0d6140beSAndroid Build Coastguard Worker };
121*0d6140beSAndroid Build Coastguard Worker const struct io_mock ch341a_spi_io = {
122*0d6140beSAndroid Build Coastguard Worker .state = &ch341a_spi_io_state,
123*0d6140beSAndroid Build Coastguard Worker .libusb_alloc_transfer = &ch341a_libusb_alloc_transfer,
124*0d6140beSAndroid Build Coastguard Worker .libusb_submit_transfer = &ch341a_libusb_submit_transfer,
125*0d6140beSAndroid Build Coastguard Worker .libusb_free_transfer = &ch341a_libusb_free_transfer,
126*0d6140beSAndroid Build Coastguard Worker .libusb_handle_events_timeout = &ch341a_libusb_handle_events_timeout,
127*0d6140beSAndroid Build Coastguard Worker .fallback_open_state = &ch341a_spi_fallback_open_state,
128*0d6140beSAndroid Build Coastguard Worker };
129*0d6140beSAndroid Build Coastguard Worker
130*0d6140beSAndroid Build Coastguard Worker run_probe_lifecycle(state, &ch341a_spi_io, &programmer_ch341a_spi, "", "W25Q128.V");
131*0d6140beSAndroid Build Coastguard Worker }
132*0d6140beSAndroid Build Coastguard Worker
133*0d6140beSAndroid Build Coastguard Worker #else
134*0d6140beSAndroid Build Coastguard Worker SKIP_TEST(ch341a_spi_basic_lifecycle_test_success)
135*0d6140beSAndroid Build Coastguard Worker SKIP_TEST(ch341a_spi_probe_lifecycle_test_success)
136*0d6140beSAndroid Build Coastguard Worker #endif /* CONFIG_CH341A_SPI */
137