/* * Copyright 2014 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include #include #include #include #include #include #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 transferred; 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), &transferred, TRANSFER_TIMEOUT_MS)); if (transferred != sizeof(command)) { fprintf(stderr, "Failed to transfer full command " "(sent %d of %d bytes)\n", transferred, (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 transferred; /* * 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), &transferred, TRANSFER_TIMEOUT_MS)); CHECK(libusb_bulk_transfer(device, LIBUSB_ENDPOINT_IN | 2, response, sizeof(response), &transferred, TRANSFER_TIMEOUT_MS)); if (transferred != sizeof(response)) { fprintf(stderr, "Failed to transfer full response " "(read %d of %d bytes)\n", transferred, (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; /* Google */ uint16_t product_id = 0x500f; /* discovery-stm32f072 */ int interface = 1; /* gpio interface */ if (!(argc == 2 && strcmp(argv[1], "read") == 0) && !(argc == 4 && strcmp(argv[1], "write") == 0)) { puts("Usage: usb_gpio read\n" " usb_gpio write \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, interface)); 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; }