diff options
author | Anton Staaf <robotboy@chromium.org> | 2014-09-10 12:37:06 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-10-14 23:59:15 +0000 |
commit | c9e71277b4af9199125fbebc389ef19aa70045ab (patch) | |
tree | 00d9fc1c3611227383d3b09163bfb8f73e1c20a0 /extra | |
parent | 46102d3b4ed4958986b2272237a33513ee32fc92 (diff) | |
download | chrome-ec-c9e71277b4af9199125fbebc389ef19aa70045ab.tar.gz |
discovery-stm32f072: discovery USB GPIO test
Wire up the discovery's four LEDs and one user
button as GPIOs that can be written and read using
the new USB GPIO driver. This also adds an extra
tool called usb_gpio that provides control of GPIOs
from the linux command line.
Signed-off-by: Anton Staaf <robotboy@chromium.org>
BRANCH=None
BUG=None
TEST=cd board/discovery-stm32f072 ; make flash
cd extra/usb_gpio ; make
usb_gpio write 0x1e 0x00
Change-Id: I15115f82b15b6c35d1a34b83b7114a6bfa6a3d67
Reviewed-on: https://chromium-review.googlesource.com/218270
Reviewed-by: Anton Staaf <robotboy@chromium.org>
Commit-Queue: Anton Staaf <robotboy@chromium.org>
Tested-by: Anton Staaf <robotboy@chromium.org>
Diffstat (limited to 'extra')
-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 |
3 files changed, 193 insertions, 0 deletions
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; +} |