diff options
-rw-r--r-- | board/discovery-stm32f072/board.c | 23 | ||||
-rw-r--r-- | board/discovery-stm32f072/board.h | 9 | ||||
-rw-r--r-- | board/discovery-stm32f072/echo.c | 9 | ||||
-rw-r--r-- | extra/usb_gpio/.gitignore | 1 | ||||
-rw-r--r-- | extra/usb_gpio/Makefile | 34 | ||||
-rw-r--r-- | extra/usb_gpio/usb_gpio.c | 158 |
6 files changed, 222 insertions, 12 deletions
diff --git a/board/discovery-stm32f072/board.c b/board/discovery-stm32f072/board.c index 9d736dcaf5..f7cef5c3cd 100644 --- a/board/discovery-stm32f072/board.c +++ b/board/discovery-stm32f072/board.c @@ -9,6 +9,7 @@ #include "hooks.h" #include "registers.h" #include "task.h" +#include "usb_gpio.h" #include "util.h" void button_event(enum gpio_signal signal); @@ -27,6 +28,28 @@ void button_event(enum gpio_signal signal) count++; } +static enum gpio_signal const usb_gpio_list[] = { + GPIO_USER_BUTTON, + GPIO_LED_U, + GPIO_LED_D, + GPIO_LED_L, + GPIO_LED_R, +}; + +USB_GPIO_CONFIG(usb_gpio, + usb_gpio_list, + USB_IFACE_GPIO, + USB_EP_GPIO) + +const void *const usb_strings[] = { + [USB_STR_DESC] = usb_string_desc, + [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), + [USB_STR_PRODUCT] = USB_STRING_DESC("discovery-stm32f072"), + [USB_STR_VERSION] = USB_STRING_DESC("v1.0"), +}; + +BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); + /* Initialize board. */ static void board_init(void) { diff --git a/board/discovery-stm32f072/board.h b/board/discovery-stm32f072/board.h index 3ef289691d..1e7d86363e 100644 --- a/board/discovery-stm32f072/board.h +++ b/board/discovery-stm32f072/board.h @@ -27,12 +27,13 @@ #define CONFIG_STM_HWTIMER32 #define CONFIG_HW_CRC #define CONFIG_USB +#define CONFIG_USB_GPIO #undef CONFIG_WATCHDOG_HELP #undef CONFIG_LID_SWITCH /* USB configuration */ -#define CONFIG_USB_PID 0x5009 +#define CONFIG_USB_PID 0x500f /* * Allow dangerous commands all the time, since we don't have a write protect @@ -61,11 +62,13 @@ enum usb_strings { /* USB interface indexes (use define rather than enum to expand them) */ #define USB_IFACE_STREAM 0 -#define USB_IFACE_COUNT 1 +#define USB_IFACE_GPIO 1 +#define USB_IFACE_COUNT 2 /* USB endpoint indexes (use define rather than enum to expand them) */ #define USB_EP_CONTROL 0 #define USB_EP_STREAM 1 -#define USB_EP_COUNT 2 +#define USB_EP_GPIO 2 +#define USB_EP_COUNT 3 #endif /* __BOARD_H */ diff --git a/board/discovery-stm32f072/echo.c b/board/discovery-stm32f072/echo.c index 08550a4b36..8fa6435458 100644 --- a/board/discovery-stm32f072/echo.c +++ b/board/discovery-stm32f072/echo.c @@ -39,15 +39,6 @@ USB_STREAM_CONFIG(usb_stream1, in_ready, out_ready) -const void *const usb_strings[] = { - [USB_STR_DESC] = usb_string_desc, - [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."), - [USB_STR_PRODUCT] = USB_STRING_DESC("discovery-stm32f072"), - [USB_STR_VERSION] = NULL /* filled at runtime */, -}; - -BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); - struct stream_console_state { size_t wrote; }; diff --git a/extra/usb_gpio/.gitignore b/extra/usb_gpio/.gitignore new file mode 100644 index 0000000000..239f1ed4d8 --- /dev/null +++ b/extra/usb_gpio/.gitignore @@ -0,0 +1 @@ +usb_gpio diff --git a/extra/usb_gpio/Makefile b/extra/usb_gpio/Makefile new file mode 100644 index 0000000000..2006c8ca67 --- /dev/null +++ b/extra/usb_gpio/Makefile @@ -0,0 +1,34 @@ +# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +PROGRAM := usb_gpio +SOURCE := $(PROGRAM).c +LIBS := +LFLAGS := +CFLAGS := -std=gnu99 \ + -g3 \ + -O3 \ + -Wall \ + -Werror \ + -Wpointer-arith \ + -Wcast-align \ + -Wcast-qual \ + -Wundef \ + -Wsign-compare \ + -Wredundant-decls \ + -Wmissing-declarations + +# +# Add libusb-1.0 required flags +# +LIBS += $(shell pkg-config --libs libusb-1.0) +CFLAGS += $(shell pkg-config --cflags libusb-1.0) + +$(PROGRAM): $(SOURCE) Makefile + gcc $(CFLAGS) $(SOURCE) $(LFLAGS) $(LIBS) -o $@ + +.PHONY: clean + +clean: + rm -rf $(PROGRAM) *~ diff --git a/extra/usb_gpio/usb_gpio.c b/extra/usb_gpio/usb_gpio.c new file mode 100644 index 0000000000..6c6d464963 --- /dev/null +++ b/extra/usb_gpio/usb_gpio.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <libusb.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define CHECK(expression) \ + ({ \ + int error__ = (expression); \ + \ + if (error__ != 0) { \ + fprintf(stderr, \ + "libusb error: %s:%d %s\n", \ + __FILE__, \ + __LINE__, \ + libusb_error_name(error__)); \ + return error__; \ + } \ + \ + error__; \ + }) + +#define TRANSFER_TIMEOUT_MS 100 + +static int gpio_write(libusb_device_handle *device, + uint32_t set_mask, + uint32_t clear_mask) +{ + uint8_t command[8]; + int transfered; + + command[0] = (set_mask >> 0) & 0xff; + command[1] = (set_mask >> 8) & 0xff; + command[2] = (set_mask >> 16) & 0xff; + command[3] = (set_mask >> 24) & 0xff; + + command[4] = (clear_mask >> 0) & 0xff; + command[5] = (clear_mask >> 8) & 0xff; + command[6] = (clear_mask >> 16) & 0xff; + command[7] = (clear_mask >> 24) & 0xff; + + CHECK(libusb_bulk_transfer(device, + LIBUSB_ENDPOINT_OUT | 2, + command, + sizeof(command), + &transfered, + TRANSFER_TIMEOUT_MS)); + + if (transfered != sizeof(command)) { + fprintf(stderr, + "Failed to transfer full command " + "(sent %d of %d bytes)\n", + transfered, + (int)sizeof(command)); + return LIBUSB_ERROR_OTHER; + } + + return 0; +} + +static int gpio_read(libusb_device_handle *device, uint32_t *mask) +{ + uint8_t response[4]; + int transfered; + + /* + * The first query does triggers the sampling of the GPIO values, the + * second query reads them back. + */ + CHECK(libusb_bulk_transfer(device, + LIBUSB_ENDPOINT_IN | 2, + response, + sizeof(response), + &transfered, + TRANSFER_TIMEOUT_MS)); + + CHECK(libusb_bulk_transfer(device, + LIBUSB_ENDPOINT_IN | 2, + response, + sizeof(response), + &transfered, + TRANSFER_TIMEOUT_MS)); + + if (transfered != sizeof(response)) { + fprintf(stderr, + "Failed to transfer full response " + "(read %d of %d bytes)\n", + transfered, + (int)sizeof(response)); + return LIBUSB_ERROR_OTHER; + } + + *mask = (response[0] << 0 | + response[1] << 8 | + response[2] << 16 | + response[3] << 24); + + return 0; +} + +int main(int argc, char **argv) +{ + libusb_context *context; + libusb_device_handle *device; + uint16_t vendor_id = 0x18d1; + uint16_t product_id = 0x500f; + + if (!(argc == 2 && strcmp(argv[1], "read") == 0) && + !(argc == 4 && strcmp(argv[1], "write") == 0)) { + puts("Usage: usb_gpio read\n" + " usb_gpio write <set_mask> <clear_mask>\n"); + return 1; + } + + CHECK(libusb_init(&context)); + + device = libusb_open_device_with_vid_pid(context, + vendor_id, + product_id); + + if (device == NULL) { + fprintf(stderr, + "Unable to find device 0x%04x:0x%04x\n", + vendor_id, + product_id); + return 1; + } + + CHECK(libusb_set_auto_detach_kernel_driver(device, 1)); + CHECK(libusb_claim_interface(device, 0)); + + if (argc == 2 && strcmp(argv[1], "read") == 0) { + uint32_t mask; + + CHECK(gpio_read(device, &mask)); + + printf("GPIO mask: 0x%08x\n", mask); + } + + if (argc == 4 && strcmp(argv[1], "write") == 0) { + uint32_t set_mask = strtol(argv[2], NULL, 0); + uint32_t clear_mask = strtol(argv[3], NULL, 0); + + CHECK(gpio_write(device, set_mask, clear_mask)); + } + + libusb_close(device); + libusb_exit(context); + + return 0; +} |