diff options
Diffstat (limited to 'developerbox_spi.c')
-rw-r--r-- | developerbox_spi.c | 93 |
1 files changed, 60 insertions, 33 deletions
diff --git a/developerbox_spi.c b/developerbox_spi.c index 4ff2fb609..64b7e8a1b 100644 --- a/developerbox_spi.c +++ b/developerbox_spi.c @@ -31,8 +31,6 @@ * should be turned on). */ -#include "platform.h" - #include <stdlib.h> #include <libusb.h> #include "programmer.h" @@ -55,20 +53,23 @@ #define CP210X_WRITE_LATCH 0x37e1 #define CP210X_READ_LATCH 0x00c2 -const struct dev_entry devs_developerbox_spi[] = { +static const struct dev_entry devs_developerbox_spi[] = { {0x10c4, 0xea60, OK, "Silicon Labs", "CP2102N USB to UART Bridge Controller"}, {0}, }; -static struct libusb_context *usb_ctx; -static libusb_device_handle *cp210x_handle; +struct devbox_spi_data { + struct libusb_context *usb_ctx; + libusb_device_handle *cp210x_handle; +}; -static int cp210x_gpio_get(void) +static int cp210x_gpio_get(void *spi_data) { int res; uint8_t gpio; + struct devbox_spi_data *data = spi_data; - res = libusb_control_transfer(cp210x_handle, REQTYPE_DEVICE_TO_HOST, + res = libusb_control_transfer(data->cp210x_handle, REQTYPE_DEVICE_TO_HOST, CP210X_VENDOR_SPECIFIC, CP210X_READ_LATCH, 0, &gpio, 1, 0); if (res < 0) { @@ -79,72 +80,79 @@ static int cp210x_gpio_get(void) return gpio; } -static void cp210x_gpio_set(uint8_t val, uint8_t mask) +static void cp210x_gpio_set(uint8_t val, uint8_t mask, void *spi_data) { int res; uint16_t gpio; + struct devbox_spi_data *data = spi_data; gpio = ((val & 0xf) << 8) | (mask & 0xf); /* Set relay state on the card */ - res = libusb_control_transfer(cp210x_handle, REQTYPE_HOST_TO_DEVICE, + res = libusb_control_transfer(data->cp210x_handle, REQTYPE_HOST_TO_DEVICE, CP210X_VENDOR_SPECIFIC, CP210X_WRITE_LATCH, gpio, NULL, 0, 0); if (res < 0) msg_perr("Failed to read GPIO pins (%s)\n", libusb_error_name(res)); } -static void cp210x_bitbang_set_cs(int val) +static void cp210x_bitbang_set_cs(int val, void *spi_data) { - cp210x_gpio_set(val << DEVELOPERBOX_SPI_CS, 1 << DEVELOPERBOX_SPI_CS); + cp210x_gpio_set(val << DEVELOPERBOX_SPI_CS, 1 << DEVELOPERBOX_SPI_CS, spi_data); } -static void cp210x_bitbang_set_sck(int val) +static void cp210x_bitbang_set_sck(int val, void *spi_data) { - cp210x_gpio_set(val << DEVELOPERBOX_SPI_SCK, 1 << DEVELOPERBOX_SPI_SCK); + cp210x_gpio_set(val << DEVELOPERBOX_SPI_SCK, 1 << DEVELOPERBOX_SPI_SCK, spi_data); } -static void cp210x_bitbang_set_mosi(int val) +static void cp210x_bitbang_set_mosi(int val, void *spi_data) { - cp210x_gpio_set(val << DEVELOPERBOX_SPI_MOSI, 1 << DEVELOPERBOX_SPI_MOSI); + cp210x_gpio_set(val << DEVELOPERBOX_SPI_MOSI, 1 << DEVELOPERBOX_SPI_MOSI, spi_data); } -static int cp210x_bitbang_get_miso(void) +static int cp210x_bitbang_get_miso(void *spi_data) { - return !!(cp210x_gpio_get() & (1 << DEVELOPERBOX_SPI_MISO)); + return !!(cp210x_gpio_get(spi_data) & (1 << DEVELOPERBOX_SPI_MISO)); } -static void cp210x_bitbang_set_sck_set_mosi(int sck, int mosi) +static void cp210x_bitbang_set_sck_set_mosi(int sck, int mosi, void *spi_data) { cp210x_gpio_set(sck << DEVELOPERBOX_SPI_SCK | mosi << DEVELOPERBOX_SPI_MOSI, - 1 << DEVELOPERBOX_SPI_SCK | 1 << DEVELOPERBOX_SPI_MOSI); + 1 << DEVELOPERBOX_SPI_SCK | 1 << DEVELOPERBOX_SPI_MOSI, + spi_data); } static const struct bitbang_spi_master bitbang_spi_master_cp210x = { - .set_cs = cp210x_bitbang_set_cs, - .set_sck = cp210x_bitbang_set_sck, - .set_mosi = cp210x_bitbang_set_mosi, - .get_miso = cp210x_bitbang_get_miso, - .set_sck_set_mosi = cp210x_bitbang_set_sck_set_mosi, + .set_cs = cp210x_bitbang_set_cs, + .set_sck = cp210x_bitbang_set_sck, + .set_mosi = cp210x_bitbang_set_mosi, + .get_miso = cp210x_bitbang_get_miso, + .set_sck_set_mosi = cp210x_bitbang_set_sck_set_mosi, }; -static int developerbox_spi_shutdown(void *data) +static int developerbox_spi_shutdown(void *spi_data) { - libusb_close(cp210x_handle); - libusb_exit(usb_ctx); + struct devbox_spi_data *data = spi_data; + libusb_close(data->cp210x_handle); + libusb_exit(data->usb_ctx); + + free(data); return 0; } -int developerbox_spi_init(void) +static int developerbox_spi_init(const struct programmer_cfg *cfg) { - libusb_init(&usb_ctx); - if (!usb_ctx) { + struct libusb_context *usb_ctx; + libusb_device_handle *cp210x_handle; + + if (libusb_init(&usb_ctx)) { msg_perr("Could not initialize libusb!\n"); return 1; } - char *serialno = extract_programmer_param("serial"); + char *serialno = extract_programmer_param_str(cfg, "serial"); if (serialno) msg_pdbg("Looking for serial number commencing %s\n", serialno); cp210x_handle = usb_dev_get_by_vid_pid_serial(usb_ctx, @@ -155,15 +163,34 @@ int developerbox_spi_init(void) goto err_exit; } - if (register_shutdown(developerbox_spi_shutdown, NULL)) + struct devbox_spi_data *data = calloc(1, sizeof(*data)); + if (!data) { + msg_perr("Unable to allocate space for SPI master data\n"); goto err_exit; + } + data->usb_ctx = usb_ctx; + data->cp210x_handle = cp210x_handle; - if (register_spi_bitbang_master(&bitbang_spi_master_cp210x)) + if (register_shutdown(developerbox_spi_shutdown, data)) { + free(data); goto err_exit; + } + + if (register_spi_bitbang_master(&bitbang_spi_master_cp210x, data)) + return 1; /* shutdown function does the cleanup */ return 0; err_exit: + if (cp210x_handle) + libusb_close(cp210x_handle); libusb_exit(usb_ctx); return 1; } + +const struct programmer_entry programmer_developerbox = { + .name = "developerbox", + .type = USB, + .devs.dev = devs_developerbox_spi, + .init = developerbox_spi_init, +}; |