summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominic Radermacher <blip@mockmoon-cybernetics.ch>2018-04-21 15:50:03 +0200
committerDominic Radermacher <blip@mockmoon-cybernetics.ch>2018-04-21 15:50:03 +0200
commitae9333e21ab1eaff37ec8fefa0e9899d13349184 (patch)
treeb2a197878ae7a6ae23d395657846ee4a1fa65f80
initial commit, turning LEDs off is workingv0.9
-rw-r--r--.gitignore5
-rw-r--r--Makefile44
-rw-r--r--README13
-rw-r--r--include/lan7800-led-ctl.h66
-rw-r--r--src/lan7800-led-ctl.c168
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) $@
diff --git a/README b/README
new file mode 100644
index 0000000..24cad87
--- /dev/null
+++ b/README
@@ -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, &reg_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);
+}