diff options
Diffstat (limited to 'raiden_debug_spi.c')
-rw-r--r-- | raiden_debug_spi.c | 192 |
1 files changed, 112 insertions, 80 deletions
diff --git a/raiden_debug_spi.c b/raiden_debug_spi.c index bd7c054de..c5642ff43 100644 --- a/raiden_debug_spi.c +++ b/raiden_debug_spi.c @@ -343,13 +343,19 @@ #include "usb_device.h" #include <libusb.h> +#include <stdbool.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -/* FIXME: Add some programmer IDs here */ -const struct dev_entry devs_raiden[] = { +/* + * Table is empty as raiden_debug_spi matches against the class and + * subclass of the connected USB devices, rather than looking for a + * device with a specific vid:pid. + */ +static const struct dev_entry devs_raiden[] = { {0}, }; @@ -398,6 +404,10 @@ enum usb_spi_error { USB_SPI_UNKNOWN_ERROR = 0x8000, }; +/* Corresponds with 'enum usb_spi_request' in, + * platform/cr50/chip/g/usb_spi.h and, + * platform/ec/chip/stm32/usb_spi.h. + */ enum raiden_debug_spi_request { RAIDEN_DEBUG_SPI_REQ_ENABLE = 0x0000, RAIDEN_DEBUG_SPI_REQ_DISABLE = 0x0001, @@ -441,6 +451,7 @@ struct raiden_debug_spi_data { */ uint16_t max_spi_write_count; uint16_t max_spi_read_count; + struct spi_master *spi_config; }; /* * USB permits a maximum bulk transfer of 64B. @@ -881,7 +892,7 @@ static int send_command_v1(const struct flashctx *flash, /* Reattempting will not result in a recovery. */ return status; } - programmer_delay(RETRY_INTERVAL_US); + default_delay(RETRY_INTERVAL_US); continue; } @@ -916,7 +927,7 @@ static int send_command_v1(const struct flashctx *flash, /* Reattempting will not result in a recovery. */ return status; } - programmer_delay(RETRY_INTERVAL_US); + default_delay(RETRY_INTERVAL_US); } } @@ -951,7 +962,7 @@ static int get_spi_config_v2(struct raiden_debug_spi_data *ctx_data) " config attempt = %d\n" " status = 0x%05x\n", config_attempt + 1, status); - programmer_delay(RETRY_INTERVAL_US); + default_delay(RETRY_INTERVAL_US); continue; } @@ -961,7 +972,7 @@ static int get_spi_config_v2(struct raiden_debug_spi_data *ctx_data) " config attempt = %d\n" " status = 0x%05x\n", config_attempt + 1, status); - programmer_delay(RETRY_INTERVAL_US); + default_delay(RETRY_INTERVAL_US); continue; } @@ -982,6 +993,22 @@ static int get_spi_config_v2(struct raiden_debug_spi_data *ctx_data) return status; } + /* + * Check if we received an error from the device. An error will have no + * response data, just the packet_id and status_code. + */ + const size_t err_packet_size = sizeof(struct usb_spi_response_v2) - + USB_SPI_PAYLOAD_SIZE_V2_RESPONSE; + if (rsp_config.packet_size == err_packet_size && + rsp_config.packet_v2.rsp_start.status_code != + USB_SPI_SUCCESS) { + status = rsp_config.packet_v2.rsp_start.status_code; + if (status == USB_SPI_DISABLED) { + msg_perr("Raiden: Target SPI bridge is disabled (is WP enabled?)\n"); + return status; + } + } + msg_perr("Raiden: Packet is not a valid config\n" " config attempt = %d\n" " packet id = %u\n" @@ -989,7 +1016,7 @@ static int get_spi_config_v2(struct raiden_debug_spi_data *ctx_data) config_attempt + 1, rsp_config.packet_v2.packet_id, rsp_config.packet_size); - programmer_delay(RETRY_INTERVAL_US); + default_delay(RETRY_INTERVAL_US); } return USB_SPI_HOST_INIT_FAILURE; } @@ -1213,7 +1240,7 @@ static int send_command_v2(const struct flashctx *flash, /* Reattempting will not result in a recovery. */ return status; } - programmer_delay(RETRY_INTERVAL_US); + default_delay(RETRY_INTERVAL_US); continue; } for (read_attempt = 0; read_attempt < READ_RETRY_ATTEMPTS; @@ -1250,22 +1277,52 @@ static int send_command_v2(const struct flashctx *flash, } /* Device needs to reset its transmit index. */ restart_response_v2(ctx_data); - programmer_delay(RETRY_INTERVAL_US); + default_delay(RETRY_INTERVAL_US); } } } return status; } +static int raiden_debug_spi_shutdown(void * data) +{ + struct raiden_debug_spi_data *ctx_data = (struct raiden_debug_spi_data *)data; + struct spi_master *spi_config = ctx_data->spi_config; + + int ret = LIBUSB(libusb_control_transfer( + ctx_data->dev->handle, + LIBUSB_ENDPOINT_OUT | + LIBUSB_REQUEST_TYPE_VENDOR | + LIBUSB_RECIPIENT_INTERFACE, + RAIDEN_DEBUG_SPI_REQ_DISABLE, + 0, + ctx_data->dev->interface_descriptor->bInterfaceNumber, + NULL, + 0, + TRANSFER_TIMEOUT_MS)); + if (ret != 0) { + msg_perr("Raiden: Failed to disable SPI bridge\n"); + free(ctx_data); + free(spi_config); + return ret; + } + + usb_device_free(ctx_data->dev); + libusb_exit(NULL); + free(ctx_data); + free(spi_config); + + return 0; +} + static const struct spi_master spi_master_raiden_debug = { - .features = SPI_MASTER_4BA, - .max_data_read = 0, - .max_data_write = 0, - .command = NULL, - .multicommand = default_spi_send_multicommand, - .read = default_spi_read, - .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, + .features = SPI_MASTER_4BA, + .max_data_read = 0, + .max_data_write = 0, + .command = NULL, + .read = default_spi_read, + .write_256 = default_spi_write_256, + .shutdown = raiden_debug_spi_shutdown, }; static int match_endpoint(struct libusb_endpoint_descriptor const *descriptor, @@ -1316,15 +1373,14 @@ static int find_endpoints(struct usb_device *dev, uint8_t *in_ep, uint8_t *out_e * is being used by the device USB SPI interface and if needed query the * device for its capabilities. * - * @param spi_config Raiden SPI config which will be modified. + * @param ctx_data Raiden SPI data, data contains pointer to config which will be modified. * - * @returns Returns status code with 0 on success. + * @returns Returns status code with 0 on success. */ -static int configure_protocol(struct spi_master *spi_config) +static int configure_protocol(struct raiden_debug_spi_data *ctx_data) { int status = 0; - struct raiden_debug_spi_data *ctx_data = - (struct raiden_debug_spi_data *)spi_config->data; + struct spi_master *spi_config = ctx_data->spi_config; ctx_data->protocol_version = ctx_data->dev->interface_descriptor->bInterfaceProtocol; @@ -1375,46 +1431,16 @@ static int configure_protocol(struct spi_master *spi_config) return 0; } -static int raiden_debug_spi_shutdown(void * data) -{ - struct spi_master *spi_config = data; - struct raiden_debug_spi_data *ctx_data = - (struct raiden_debug_spi_data *)spi_config->data; - - int ret = LIBUSB(libusb_control_transfer( - ctx_data->dev->handle, - LIBUSB_ENDPOINT_OUT | - LIBUSB_REQUEST_TYPE_VENDOR | - LIBUSB_RECIPIENT_INTERFACE, - RAIDEN_DEBUG_SPI_REQ_DISABLE, - 0, - ctx_data->dev->interface_descriptor->bInterfaceNumber, - NULL, - 0, - TRANSFER_TIMEOUT_MS)); - if (ret != 0) { - msg_perr("Raiden: Failed to disable SPI bridge\n"); - free(ctx_data); - free(spi_config); - return ret; - } - - usb_device_free(ctx_data->dev); - libusb_exit(NULL); - free(ctx_data); - free(spi_config); - - return 0; -} - -static int get_ap_request_type(void) +static int get_ap_request_type(const struct programmer_cfg *cfg) { int ap_request = RAIDEN_DEBUG_SPI_REQ_ENABLE_AP; - char *custom_rst_str = extract_programmer_param("custom_rst"); + char *custom_rst_str = extract_programmer_param_str(cfg, "custom_rst"); if (custom_rst_str) { - if (!strcasecmp(custom_rst_str, "true")) + if (!strcasecmp(custom_rst_str, "true")) { ap_request = RAIDEN_DEBUG_SPI_REQ_ENABLE_AP_CUSTOM; - else { + } else if (!strcasecmp(custom_rst_str, "false")) { + ap_request = RAIDEN_DEBUG_SPI_REQ_ENABLE_AP; + } else { msg_perr("Invalid custom rst param: %s\n", custom_rst_str); ap_request = -1; @@ -1424,14 +1450,18 @@ static int get_ap_request_type(void) return ap_request; } -static int get_target(void) +static int get_target(const struct programmer_cfg *cfg) { + /** + * REQ_ENABLE doesn't specify a target bus, and will be rejected + * by adapters that support more than one target. + */ int request_enable = RAIDEN_DEBUG_SPI_REQ_ENABLE; - char *target_str = extract_programmer_param("target"); + char *target_str = extract_programmer_param_str(cfg, "target"); if (target_str) { if (!strcasecmp(target_str, "ap")) - request_enable = get_ap_request_type(); + request_enable = get_ap_request_type(cfg); else if (!strcasecmp(target_str, "ec")) request_enable = RAIDEN_DEBUG_SPI_REQ_ENABLE_EC; else { @@ -1454,22 +1484,22 @@ static void free_dev_list(struct usb_device **dev_lst) dev = usb_device_free(dev); } -int raiden_debug_spi_init(void) +static int raiden_debug_spi_init(const struct programmer_cfg *cfg) { struct usb_match match; - char *serial = extract_programmer_param("serial"); + char *serial = extract_programmer_param_str(cfg, "serial"); struct usb_device *current; struct usb_device *device = NULL; - int found = 0; + bool found = false; int ret; - int request_enable = get_target(); + int request_enable = get_target(cfg); if (request_enable < 0) { free(serial); return 1; } - usb_match_init(&match); + usb_match_init(cfg, &match); usb_match_value_default(&match.vid, GOOGLE_VID); usb_match_value_default(&match.class, LIBUSB_CLASS_VENDOR_SPEC); @@ -1507,15 +1537,13 @@ int raiden_debug_spi_init(void) } if (!serial) { - found = 1; + found = true; goto loop_end; } else { - unsigned char dev_serial[32]; + unsigned char dev_serial[32] = { 0 }; struct libusb_device_descriptor descriptor; int rc; - memset(dev_serial, 0, sizeof(dev_serial)); - if (libusb_get_device_descriptor(device->device, &descriptor)) { msg_pdbg("USB: Failed to get device descriptor.\n"); goto loop_end; @@ -1534,7 +1562,7 @@ int raiden_debug_spi_init(void) } else { msg_pinfo("Raiden: Serial number %s matched device", serial); usb_device_show(" ", current); - found = 1; + found = true; } } } @@ -1579,31 +1607,31 @@ loop_end: (request_enable == RAIDEN_DEBUG_SPI_REQ_ENABLE_EC)) usleep(50 * 1000); - struct spi_master *spi_config = calloc(1, sizeof(struct spi_master)); + struct spi_master *spi_config = calloc(1, sizeof(*spi_config)); if (!spi_config) { msg_perr("Unable to allocate space for SPI master.\n"); return SPI_GENERIC_ERROR; } - struct raiden_debug_spi_data *data = calloc(1, sizeof(struct raiden_debug_spi_data)); + struct raiden_debug_spi_data *data = calloc(1, sizeof(*data)); if (!data) { free(spi_config); msg_perr("Unable to allocate space for extra SPI master data.\n"); return SPI_GENERIC_ERROR; } - memcpy(spi_config, &spi_master_raiden_debug, sizeof(struct spi_master)); + *spi_config = spi_master_raiden_debug; data->dev = device; data->in_ep = in_endpoint; data->out_ep = out_endpoint; + data->spi_config = spi_config; - spi_config->data = data; /* * The SPI master needs to be configured based on the device connected. * Using the device protocol interrogation, we will set the limits on * the write and read sizes and switch command functions. */ - ret = configure_protocol(spi_config); + ret = configure_protocol(data); if (ret) { msg_perr("Raiden: Error configuring protocol\n" " protocol = %u\n" @@ -1614,8 +1642,12 @@ loop_end: return SPI_GENERIC_ERROR; } - register_spi_master(spi_config); - register_shutdown(raiden_debug_spi_shutdown, spi_config); - - return 0; + return register_spi_master(spi_config, data); } + +const struct programmer_entry programmer_raiden_debug_spi = { + .name = "raiden_debug_spi", + .type = USB, + .devs.dev = devs_raiden, + .init = raiden_debug_spi_init, +}; |