diff options
author | Dominic Radermacher <blip@mockmoon-cybernetics.ch> | 2018-04-21 15:50:03 +0200 |
---|---|---|
committer | Dominic Radermacher <blip@mockmoon-cybernetics.ch> | 2018-04-21 15:50:03 +0200 |
commit | ae9333e21ab1eaff37ec8fefa0e9899d13349184 (patch) | |
tree | b2a197878ae7a6ae23d395657846ee4a1fa65f80 |
initial commit, turning LEDs off is workingv0.9
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | Makefile | 44 | ||||
-rw-r--r-- | README | 13 | ||||
-rw-r--r-- | include/lan7800-led-ctl.h | 66 | ||||
-rw-r--r-- | src/lan7800-led-ctl.c | 168 |
5 files changed, 296 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6ec8668 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# C-Objects +*.o + +# Binary +lan7800-led-ctl diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ee08d4d --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +ECHO = /bin/echo -e +SHELL = /bin/sh +RM = /bin/rm -f +CC = gcc +STRIP = strip + +GIT_VERSION := $(shell git --no-pager describe --tags --dirty |sed 's/\([^-]*-g\)/r\1/;s/-/./g') + +CFLAGS = -g -Os -std=c11 -I./include -Wall -Wstrict-prototypes -Wconversion +CFLAGS += -DVERSION=\"$(GIT_VERSION)\" +CFLAGS += -Wmissing-prototypes -Wshadow -Wextra -Wunused +LDFLAGS = -lusb-1.0 + +PROGS = lan7800-led-ctl + +all: $(PROGS) + +clean: + $(RM) src/*.o +tidy: + $(RM) src/*.o $(PROGS) + +install: $(PROGS) + @$(ECHO) "\t==> Installing programs to $(DESTDIR)/usr/bin" + @install -m 0755 -d $(DESTDIR)/usr/bin + @install -m 0755 -t $(DESTDIR)/usr/bin $(PROGS) + +pack: + @$(ECHO) "Cleaning up ..." ; \ + $(RM) src/*.o $(PROGS) + @$(ECHO) "Creating package ..." ; \ + cd .. ; \ + tar c -J -f lan7800-led-ctl-$(GIT_VERSION).tar.xz lan7800-led-ctl + +# Generic instructions +src/%.o: src/%.c + @$(ECHO) "\t--> Compiling `basename $<`" + @$(CC) $(CFLAGS) -c $< -o $@ + +# Specific programs +lan7800-led-ctl: src/lan7800-led-ctl.o + @$(ECHO) "\t==> Linking objects to output file $@ $(GIT_VERSION)\n" + @$(CC) $(CFLAGS) $(LDFLAGS) $+ -o $@ + @$(STRIP) $@ @@ -0,0 +1,13 @@ + +lan7800-led-ctl is a command line tool to control the LEDs connected to a +LAN7800 ethernet controller. + +Usually those LEDs show the ethernet status like "Link/Activity" and "Speed". +Using this tool you can turn them off, if you don't like a disco in your room +at night ;-) + +These ethernet and USB controllers are used on embedded computers like +Raspberry Pi 3B+. + +Further info can be found at: +https://mockmoon-cybernetics.ch/computer/raspberry-pi/lan7800-led-ctl/ diff --git a/include/lan7800-led-ctl.h b/include/lan7800-led-ctl.h new file mode 100644 index 0000000..8af9620 --- /dev/null +++ b/include/lan7800-led-ctl.h @@ -0,0 +1,66 @@ +/* + lan7800-led-ctl - control LEDs of LAN7800 ethernet/usb controllers + + Copyright (C) 2018 Dominic Radermacher <dominic@familie-radermacher.ch> + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 3 as + published by the Free Software Foundation + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define USB_CTRL_TIMEOUT (5000) +#define LAN7800_VENDOR_ID (0x0424) +#define LAN7800_PRODUCT_ID (0x7800) + +/* values from LAN7800 databook */ +#define USB_VENDOR_REQUEST_WR_REG (0xa0) +#define USB_VENDOR_REQUEST_RD_REG (0xa1) + +/* register adresses - from LAN7800 databook */ +#define REG_HW_CFG (0x10) /* hardware config register */ +/* bit 20-23: LED0-LED3 enable */ +#define REG_GPIO_CFG0 (0x18) + +/* meaning of the (relevant) bits in the HW_CFG register */ +#define HW_CFG_LED0_EN (1<<20) +#define HW_CFG_LED1_EN (1<<21) +#define HW_CFG_LED2_EN (1<<22) +#define HW_CFG_LED3_EN (1<<23) +/* meaning of the (relevant) bits in the GPIO_CFG0 register */ +#define GPIO_CFG0_GPIOEN0 (1<<12) +#define GPIO_CFG0_GPIOEN1 (1<<13) +#define GPIO_CFG0_GPIOBUF0 (1<<8) +#define GPIO_CFG0_GPIOBUF1 (1<<9) +#define GPIO_CFG0_GPIODIR0 (1<<4) +#define GPIO_CFG0_GPIODIR1 (1<<5) +#define GPIO_CFG0_GPIOD0 (1<<0) +#define GPIO_CFG0_GPIOD1 (1<<1) + +/* */ +#define HW_CFG_LED_EN (HW_CFG_LED0_EN|HW_CFG_LED1_EN) + +#define LED0_MASK (HW_CFG_LED0_EN|GPIO_CFG0_GPIOD0|GPIO_CFG0_GPIODIR0|GPIO_CFG0_GPIOBUF0|GPIO_CFG0_GPIOEN0) +#define LED1_MASK (HW_CFG_LED1_EN|GPIO_CFG0_GPIOD1|GPIO_CFG0_GPIODIR1|GPIO_CFG0_GPIOBUF1|GPIO_CFG0_GPIOEN1) + +#define MODE_OFF 0 +#define MODE_ON 1 +#define MODE_STATUS 2 +#define MODE_KEEP 4 +#define MODE_ERR -1 + +void usage(void); +void about(void); +int ledmode(const char* str); +int parse_args(int argc, char **argv); +libusb_device_handle *usbdev_open(int vid, int pid); +int lan7800_rd_reg(libusb_device_handle *h, uint16_t reg, uint32_t *val); +int lan7800_wr_reg(libusb_device_handle *h, uint16_t reg, uint32_t val); diff --git a/src/lan7800-led-ctl.c b/src/lan7800-led-ctl.c new file mode 100644 index 0000000..eeb5479 --- /dev/null +++ b/src/lan7800-led-ctl.c @@ -0,0 +1,168 @@ +/* + lan7800-led-ctl - control LEDs of LAN7800 ethernet/usb controllers + + Copyright (C) 2018 Dominic Radermacher <dominic@familie-radermacher.ch> + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 3 as + published by the Free Software Foundation + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <stdio.h> +#include <stdlib.h> /* exit() */ +#include <string.h> /* strlen() */ +#include <stdint.h> +#include <libusb-1.0/libusb.h> + +#include "lan7800-led-ctl.h" + +/* global variables */ +int led_arr[3] = { MODE_KEEP, MODE_KEEP, MODE_KEEP }; + +libusb_device_handle *usbdev_open(int vid, int pid) +{ + libusb_device **devs; + libusb_device *dev; + libusb_device_handle *handle = NULL; + struct libusb_device_descriptor desc; + int r,i=0; + + if ((libusb_init(NULL)) < 0) { + fprintf(stderr, "libusb_init() failed\n"); + return NULL; + } + if (libusb_get_device_list(NULL, &devs) < 0) { + return NULL; + } + while ((dev=devs[i++]) != NULL) { + if ((r=libusb_get_device_descriptor(dev, &desc)) < 0) { + fprintf(stderr, "failed to get device descriptor"); + libusb_free_device_list(devs, 1); + return NULL; + } + if ((desc.idVendor == vid) && (desc.idProduct == pid)) { + if ((r=libusb_open(dev, &handle)) != 0) { + fprintf(stderr, "libusb_open error :%s\n", libusb_error_name(r)); + return NULL; + } + libusb_free_device_list(devs, 1); + return handle; + } + } + libusb_free_device_list(devs, 1); + return NULL; +} + +int lan7800_rd_reg(libusb_device_handle *h, uint16_t reg, uint32_t *val) +{ + return libusb_control_transfer(h, LIBUSB_REQUEST_TYPE_VENDOR|0x80, + USB_VENDOR_REQUEST_RD_REG, 0, reg, (uint8_t *)val, 4, + USB_CTRL_TIMEOUT); +} + +int lan7800_wr_reg(libusb_device_handle *h, uint16_t reg, uint32_t val) +{ + return libusb_control_transfer(h, LIBUSB_REQUEST_TYPE_VENDOR, + USB_VENDOR_REQUEST_WR_REG, 0, reg, (uint8_t *)&val, 4, + USB_CTRL_TIMEOUT); +} + +int ledmode(const char* s) +{ + if (*s == '0') { + return MODE_OFF; + } else if (*s == '1') { + return MODE_ON; + } else if ((*s == 's') || (*s == 'S')) { + return MODE_STATUS; + } + return MODE_ERR; +} + +void usage(void) +{ + printf("usage: lan7800-led-ctl [--led0=x][--led1=x]\n"); + printf("\twhere x is one of:\n"); + printf("\t0 - turn LED off\n\t1 - turn LED on\n\ts - LED shows status\n"); + exit(1); +} + +void about(void) +{ + printf("lan7800-led-ctl %s programmed by Dominic Radermacher\n", VERSION); + printf("For further info or latest version see\n"); + printf("https://mockmoon-cybernetics.ch/computer/raspberry-pi/lan7800-led-ctl/\n"); + exit(1); +} + +int parse_args(int argc, char **argv) +{ + int i; + + for (i=1; i<argc; i++) { + char *p=argv[i]; + if (strncmp(p, "--led0=", 7) == 0) { + led_arr[0] = ledmode(p+7); + printf("setting LED0 to status %i\n", led_arr[0]); + } else if (strncmp(p, "--led1=", 7) == 0) { + led_arr[1] = ledmode(p+7); + printf("setting LED1 to status %i\n", led_arr[1]); + } else if (strcmp(p, "--about") == 0) { + about(); + } else if (strcmp(p, "--version") == 0) { + about(); + } else { + usage(); + } + } + return i; +} + +int main(int argc, char *argv[]) +{ + libusb_device_handle *handle = NULL; + uint32_t reg_hw_cfg; + uint32_t gp_mask[2]; + + gp_mask[0] = LED0_MASK; + gp_mask[1] = LED1_MASK; + if (argc < 2) { + printf("at least one argument is required\n"); + usage(); + } + parse_args(argc, argv); + if ((handle=usbdev_open(LAN7800_VENDOR_ID, LAN7800_PRODUCT_ID)) == NULL) { + printf("No LAN7800 found on USB (are you root?)\n"); + exit(1); + } + lan7800_rd_reg(handle, REG_HW_CFG, ®_hw_cfg); +#ifdef DEBUG + printf("read HW_CFG register: %08x\n", reg_hw_cfg); +#endif + for (int i=0; i < 2; i++) { + if (led_arr[i] == MODE_ON) { + reg_hw_cfg &= ~(gp_mask[i] & HW_CFG_LED_EN); + printf("turning LED on not supported yet\n"); + } + if (led_arr[i] == MODE_OFF) { + reg_hw_cfg &= ~(gp_mask[i] & HW_CFG_LED_EN); + } + if (led_arr[i] == MODE_STATUS) { + reg_hw_cfg |= (gp_mask[i] & HW_CFG_LED_EN); + } + } +#ifdef DEBUG + printf("write %08x to HG_CFG\n", reg_hw_cfg); +#endif + lan7800_wr_reg(handle, REG_HW_CFG, reg_hw_cfg); + libusb_close(handle); +} |