summaryrefslogtreecommitdiff
path: root/src/lan951x-led-ctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lan951x-led-ctl.c')
-rw-r--r--src/lan951x-led-ctl.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/src/lan951x-led-ctl.c b/src/lan951x-led-ctl.c
new file mode 100644
index 0000000..c60884c
--- /dev/null
+++ b/src/lan951x-led-ctl.c
@@ -0,0 +1,162 @@
+/*
+ lan951x-led-ctl - control LEDs of LAN951X ethernet/usb controllers
+
+ Copyright (C) 2015 Dominic Radermacher <dominic.radermacher@gmail.com>
+
+ 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 "lan951x-led-ctl.h"
+
+/* global variables */
+int led_arr[3] = { MODE_KEEP, MODE_KEEP, MODE_KEEP };
+
+libusb_device_handle *lan951x_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;
+ }
+// libusb_set_debug(NULL, 3);
+ 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)) {
+// fprintf(stderr, "LAN951x found on USB bus %d, device %d\n",
+// libusb_get_bus_number(dev),
+// libusb_get_device_address(dev));
+ 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;
+ }
+ }
+ fprintf(stderr, "No LAN951x found on USB\n");
+ libusb_free_device_list(devs, 1);
+ return NULL;
+}
+
+int lan951x_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 lan951x_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: lan951x-led-ctl [--fdx=x][--lnk=x][--spd=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);
+}
+
+int parse_args(int argc, char **argv)
+{
+ int i;
+
+ for (i=1; i<argc; i++) {
+ char *p=argv[i];
+ if (strncmp(p, "--fdx=", 6) == 0) {
+ led_arr[DUPIDX] = ledmode(p+6);
+ printf("setting FDX LED to status %i\n", led_arr[DUPIDX]);
+ } else if (strncmp(p, "--lnk=", 6) == 0) {
+ led_arr[LNKIDX] = ledmode(p+6);
+ printf("setting LNK LED to status %i\n", led_arr[LNKIDX]);
+ } else if (strncmp(p, "--spd=", 6) == 0) {
+ led_arr[SPDIDX] = ledmode(p+6);
+ printf("setting SPD LED to status %i\n", led_arr[SPDIDX]);
+ } else {
+ usage();
+ }
+ }
+ return i;
+}
+
+int main(int argc, char *argv[])
+{
+ libusb_device_handle *handle = NULL;
+ uint32_t val;
+
+ if (argc < 2) {
+ printf("at least one argument is required\n");
+ usage();
+ }
+ parse_args(argc, argv);
+
+ uint32_t gp_mask[3];
+ gp_mask[DUPIDX] = DUP_MASK;
+ gp_mask[LNKIDX] = LNK_MASK;
+ gp_mask[SPDIDX] = SPD_MASK;
+
+ if ((handle=lan951x_open(LAN951X_VENDOR_ID, LAN951X_PRODUCT_ID)) == NULL) {
+ printf("can not open usb device. are you root?\n");
+ exit(1);
+ }
+ lan951x_rd_reg(handle, LED_GPIO_CFG, &val);
+ for (int i=0; i < 3; i++) {
+ if (led_arr[i] == MODE_ON) {
+ val &= ~(gp_mask[i] & (GP_ALLCTL|GP_ALLDAT));
+ val |= (gp_mask[i] & GP_ALLDIR);
+ }
+ if (led_arr[i] == MODE_OFF) {
+ val &= ~(gp_mask[i] & GP_ALLCTL);
+ val |= (gp_mask[i] & (GP_ALLDIR|GP_ALLDAT));
+ }
+ if (led_arr[i] == MODE_STATUS) {
+ val &= ~(gp_mask[i] & (GP_ALLDIR|GP_ALLDAT));
+ val |= (gp_mask[i] & GP_ALLCTL);
+ }
+ }
+ lan951x_wr_reg(handle, LED_GPIO_CFG, val);
+ libusb_close(handle);
+}