add USBrelay

This commit is contained in:
eddyem 2020-10-13 00:01:41 +03:00
parent 62a19346cf
commit 2656ac3d43
13 changed files with 536 additions and 12 deletions

102
Binary_search/errors.c Normal file
View File

@ -0,0 +1,102 @@
/*
* Copyright 2020 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#include "errors.h"
#include <stdlib.h>
#include <stdio.h>
static const abortcodes AC[] = {
//while read l; do N=$(echo $l|awk '{print $1 $2}'); R=$(echo $l|awk '{$1=$2=""; print substr($0,3)}'|sed 's/\.//'); echo -e "{0x$N, \"$R\"},"; done < codes.b
{0x05030000, "Toggle bit not alternated"},
{0x05040000, "SDO protocol timed out"},
{0x05040001, "Client/server command specifier not valid or unknown"},
{0x05040002, "Invalid block size (block mode only)"},
{0x05040003, "Invalid sequence number (block mode only)"},
{0x05040004, "CRC error (block mode only)"},
{0x05040005, "Out of memory"},
{0x06010000, "Unsupported access to an object"},
{0x06010001, "Attempt to read a write only object"},
{0x06010002, "Attempt to write a read only object"},
{0x06020000, "Object does not exist in the object dictionary"},
{0x06040041, "Object cannot be mapped to the PDO"},
{0x06040042, "The number and length of the objects to be mapped would exceed PDO length"},
{0x06040043, "General parameter incompatibility reason"},
{0x06040047, "General internal incompatibility in the device"},
{0x06060000, "Access failed due to a hardware error"},
{0x06070010, "Data type does not match; length of service parameter does not match"},
{0x06070012, "Data type does not match; length of service parameter too high"},
{0x06070013, "Data type does not match; length of service parameter too low"},
{0x06090011, "Sub-index does not exist"},
{0x06090030, "Value range of parameter exceeded (only for write access)"},
{0x06090031, "Value of parameter written too high"},
{0x06090032, "Value of parameter written too low"},
{0x06090036, "Maximum value is less than minimum value"},
{0x08000000, "General error"},
{0x08000020, "Data cannot be transferred or stored to the application"},
{0x08000021, "Data cannot be transferred or stored to the application because of local control"},
{0x08000022, "Data cannot be transferred or stored to the application because of the present device state"},
{0x08000023, "Object dictionary dynamic generation fails or no object dictionary is present"},
};
const int ACmax = sizeof(AC)/sizeof(abortcodes) - 1;
const char *ACtext(uint32_t abortcode, int *n){
int idx = ACmax/2, min_ = 0, max_ = ACmax, newidx = 0, iter=0;
do{
++iter;
uint32_t c = AC[idx].code;
printf("idx=%d, min=%d, max=%d\n", idx, min_, max_);
if(c == abortcode){
if(n) *n = iter;
return AC[idx].errmsg;
}else if(c > abortcode){
newidx = (idx + min_)/2;
max_ = idx;
}else{
newidx = (idx + max_ + 1)/2;
min_ = idx;
}
if(newidx == idx || min_ < 0 || max_ > ACmax){
if(n) *n = 0;
return NULL;
}
idx = newidx;
}while(1);
}
void check_all(){
int iter = 0, N;
for(int i = 0; i <= ACmax; ++i){
printf("code 0x%X: %s\n\n", AC[i].code, ACtext(AC[i].code, &N));
iter += N;
}
printf("\n\ntotal: %d iterations, mean: %d, (%d for direct lookup)\n", iter, iter/(ACmax+1), (ACmax+1)/2);
}
int main(int argc, char **argv){
if(argc != 2){
check_all();
return 0;
}
uint32_t x = (uint32_t)strtol(argv[1], NULL, 0);
printf("x=0x%X\n", x);
const char *text = ACtext(x, NULL);
if(text) printf("%s\n", text);
else printf("Unknown error code\n");
return 0;
}

28
Binary_search/errors.h Normal file
View File

@ -0,0 +1,28 @@
/*
* Copyright 2020 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef ERRORS_H__
#define ERRORS_H__
#include <stdint.h>
typedef struct{
uint32_t code;
char *errmsg;
} abortcodes;
#endif // ERRORS_H__

8
README
View File

@ -7,8 +7,12 @@ B-trees - simple but slowly binary search trees with all main operations
fifo_lifo - simple stack-like queues
netdaemon - snippet for network management of serial devices
simple_list - 1-directional list with functions: add element; delete list
stellarium_emul - snippet for stellarium telescope remote control
tmout - theads-based timeout to check something
usefull_macros - a lot of different macros & functions
@ -18,6 +22,4 @@ usefull_macros - a lot of different macros & functions
* error/warning/debug macros
* MMAP files into memory
stellarium_emul - snippet for stellarium telescope remote control
netdaemon - snippet for network management of serial devices
USBrelay - simplest tool to manage USB-HID chinese relays

196
USBrelay/1.c Normal file
View File

@ -0,0 +1,196 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Hidraw Userspace Example
*
* Copyright (c) 2010 Alan Ott <alan@signal11.us>
* Copyright (c) 2010 Signal 11 Software
*
* The code may be used by anyone for any purpose,
* and can serve as a starting point for developing
* applications using hidraw.
*/
/*
* Copyright 2020 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <fcntl.h>
#include <libudev.h>
#include <linux/hidraw.h>
#include <linux/input.h>
#include <linux/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <usefull_macros.h>
// chinese USB-HID relay management
// works only with one relay (the first found or pointed)
#define RELAY_VENDOR_ID 0x16c0
#define RELAY_PRODUCT_ID 0x05df
char *device = NULL; // device name
int help = 0; // call help
int quiet = 0; // no info messages
int **set = NULL; // turn ON given relays
int **reset = NULL; // turn OFF given relays
int fd = 0; // device file descriptor
static myoption cmdlnopts[] = {
// common options
{"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")},
{"device", NEED_ARG, NULL, 'd', arg_string, APTR(&device), _("serial device name")},
{"set", MULT_PAR, NULL, 's', arg_int, APTR(&set), _("turn ON relays with given number[s]")},
{"reset", MULT_PAR, NULL, 'r', arg_int, APTR(&reset), _("turn OFF relays with given number[s]")},
{"quiet", NO_ARGS, NULL, 'q', arg_int, APTR(&quiet), _("don't show info messages")},
end_option
};
static void parse_args(int argc, char **argv){
int i;
char helpstring[1024];
snprintf(helpstring, 1024, "Usage: %%s [args]\n\n\tWhere args are:\n");
change_helpstring(helpstring);
parseargs(&argc, &argv, cmdlnopts);
if(help) showhelp(-1, cmdlnopts);
if(argc > 0){
WARNX("Wrong parameters:");
for (i = 0; i < argc; i++)
fprintf(stderr, "\t%s\n", argv[i]);
showhelp(-1, cmdlnopts);
}
}
#define CMD_ON 0xff
#define CMD_OFF 0xfd
#define CMD_SETSER 0xfa
/**
* @brief relay_cmd - turn on/off given relay
* @param cmd: CMD_ON/CMD_OFF
* @param relaynmbr - 1..8
*/
static void relay_cmd(int cmd, int relaynmbr){
char buf[9] = {0};
// buf[0] = 0x00; /* Report Number */
buf[1] = cmd; // ON - ff, OFF - fd; SET_SERIAL - 0xfa
buf[2] = relaynmbr; // relay number or [2]..[6] - new serial
int res = ioctl(fd, HIDIOCSFEATURE(9), buf);
if(res < 0)
ERR("HIDIOCSFEATURE");
else if(res != 9) ERRX("Wrong return value: %d instead of 9", res);
}
#define INFO(...) do{if(!quiet){green(__VA_ARGS__); printf("\n");}}while(0)
int main(int argc, char **argv){
int res;
char buf[256];
struct hidraw_report_descriptor rpt_desc;
struct hidraw_devinfo info;
initial_setup();
parse_args(argc, argv);
if(!device) ERRX("No device given");
fd = open(device, O_RDWR|O_NONBLOCK);
if(fd < 0){
WARN("Unable to open device");
return 1;
}
memset(&rpt_desc, 0x0, sizeof(rpt_desc));
memset(&info, 0x0, sizeof(info));
memset(buf, 0x0, sizeof(buf));
/* Get Raw Name */
res = ioctl(fd, HIDIOCGRAWNAME(256), buf);
if(res < 0)
ERR("HIDIOCGRAWNAME");
else
INFO("Raw Name: %s\n", buf);
int L = strlen(buf), wrong = 0;
char nr = '0';
if(L < 9) wrong = 1;
else{
if(strncmp(buf+L-9, "USBRelay", 8)) wrong = 1;
nr = buf[L-1];
if(nr < '0' || nr > '8') wrong = 1;
}
/* Get Raw Info */
res = ioctl(fd, HIDIOCGRAWINFO, &info);
if(res < 0){
ERR("HIDIOCGRAWINFO");
}else{
if(info.vendor != RELAY_VENDOR_ID || info.product != RELAY_PRODUCT_ID) wrong = 1;
}
if(wrong){
ERRX("Wrong relay raw name: %s (VID=0x%04X, PID=0x%04X)", buf, info.vendor, info.product);
}
int Nrelays = nr - '0';
INFO("N relays = %d", Nrelays);
if(set || reset){
if(set) do{
int On = **set;
if(On < 0 || On > Nrelays) WARNX("Wrong relay number: %d", On);
else{
INFO("SET: %d\n", On);
relay_cmd(CMD_ON, On);
}
++set;
}while(*set);
if(reset) do{
int Off = **reset;
if(Off < 0 || Off > Nrelays) WARNX("Wrong relay number: %d", Off);
else{
INFO("RESET: %d\n", Off);
relay_cmd(CMD_OFF, Off);
}
++reset;
}while(*reset);
}
/* Get Feature */
buf[0] = 0x01; /* Report Number */
memset(buf+1, 0, 8);
res = ioctl(fd, HIDIOCGFEATURE(9), buf);
if(res < 0){
ERR("HIDIOCGFEATURE");
}else{
if(res != 9) ERRX("Bad answer");
// report:
// bytes 0..4 - serial (e.g. HURTM)
// byte 7 - state (each bit of state ==1 - ON, ==0 - off)
buf[5] = 0;
INFO("Relay serial: %s", buf);
for(int i = 0; i < Nrelays; ++i){
INFO("Relay%d=%d", i, buf[7]&(1<<i)?1:0);
}
}
close(fd);
return 0;
}

View File

@ -0,0 +1 @@
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05df", MODE:="0666", SYMLINK+="relay%n"

56
USBrelay/Makefile Normal file
View File

@ -0,0 +1,56 @@
# run `make DEF=...` to add extra defines
PROGRAM := relay_manage
LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all
LDFLAGS += -lusefull_macros
SRCS := $(wildcard *.c)
DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111
OBJDIR := mk
CFLAGS += -O2 -Wall -Wextra -Wno-trampolines -std=gnu99
OBJS := $(addprefix $(OBJDIR)/, $(SRCS:%.c=%.o))
DEPS := $(OBJS:.o=.d)
CC = gcc
#CXX = g++
TARGET := RELEASE
all: $(OBJDIR)/RELEASE
all: $(PROGRAM)
release: all
debug: CFLAGS += -DEBUG -Werror
debug: TARGET := DEBUG
debug: $(OBJDIR)/DEBUG
debug: $(PROGRAM)
$(OBJDIR)/DEBUG:
@make clean
$(OBJDIR)/RELEASE:
@make clean
$(PROGRAM) : $(OBJDIR) $(OBJS)
@echo -e "\t\tTARGET: $(TARGET)"
@> $(OBJDIR)/$(TARGET)
@echo -e "\t\tLD $(PROGRAM)"
$(CC) $(LDFLAGS) $(OBJS) -o $(PROGRAM)
$(OBJDIR):
@mkdir $(OBJDIR)
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif
$(OBJDIR)/%.o: %.c
@echo -e "\t\tCC $<"
$(CC) -MD -c $(LDFLAGS) $(CFLAGS) $(DEFINES) -o $@ $<
clean:
@echo -e "\t\tCLEAN"
@rm -rf $(OBJDIR) 2>/dev/null || true
xclean: clean
@rm -f $(PROGRAM)
gentags:
CFLAGS="$(CFLAGS) $(DEFINES)" geany -g $(PROGRAM).c.tags *[hc] 2>/dev/null
.PHONY: gentags clean xclean

View File

@ -118,7 +118,7 @@ void radtodeg(double r){
double getta(char *str){
int a,b,s = 1; double c;
if(3 != sscanf(str, "%d:%d:%lf", &a,&b,&c)) return -1;
if(a < 0){ s = -1; a = -a;}
if(a < 0 || *str == '-'){ s = -1; a = -a;}
c /= 3600.;
c += a + b/60.;
c *= s;
@ -217,6 +217,8 @@ int main (int argc, char **argv){
dut1 = 0.13026 ; // DUT1
/* ICRS to observed. */
double aob, zob, hob, dob, rob;
printf("iauAtco13(%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g)\n",
rc, dc, pr, pd, px, rv, utc1, utc2, dut1, elong, phi, hm, xp, yp, phpa, tc, rh, wl);
if ( iauAtco13 ( rc, dc, pr,
pd, px, rv, utc1, utc2, dut1, elong, phi,
hm, xp, yp, phpa, tc, rh, wl, &aob, &zob,

View File

@ -0,0 +1,69 @@
cmake_minimum_required(VERSION 3.0)
set(PROJ steppermove)
set(MINOR_VERSION "1")
set(MID_VERSION "0")
set(MAJOR_VERSION "0")
set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}")
project(${PROJ} VERSION ${PROJ_VERSION} LANGUAGES C)
#enable_language(C)
message("VER: ${VERSION}")
# default flags
set(CMAKE_C_FLAGS_RELEASE "")
set(CMAKE_C_FLAGS_DEBUG "")
set(CMAKE_C_FLAGS "-O2 -std=gnu99")
set(CMAKE_COLOR_MAKEFILE ON)
# here is one of two variants: all .c in directory or .c files in list
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SOURCES)
# cmake -DDEBUG=1 -> debugging
if(DEFINED EBUG)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra -Wall -Werror -W")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra -Wall -Werror -W")
set(CMAKE_BUILD_TYPE DEBUG)
set(CMAKE_VERBOSE_MAKEFILE "ON")
add_definitions(-DEBUG)
else()
set(CMAKE_BUILD_TYPE RELEASE)
endif()
###### pkgconfig ######
# pkg-config modules (for pkg-check-modules)
set(MODULES usefull_macros)
# find packages:
find_package(PkgConfig REQUIRED)
pkg_check_modules(${PROJ} REQUIRED ${MODULES})
###### additional flags ######
#list(APPEND ${PROJ}_LIBRARIES "-lfftw3_threads")
# change wrong behaviour with install prefix
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND CMAKE_INSTALL_PREFIX MATCHES "/usr/local")
else()
message("Change default install path to /usr/local")
set(CMAKE_INSTALL_PREFIX "/usr/local")
endif()
message("Install dir prefix: ${CMAKE_INSTALL_PREFIX}")
# exe file
add_executable(${PROJ} ${SOURCES})
# -I
include_directories(${${PROJ}_INCLUDE_DIRS})
# -L
link_directories(${${PROJ}_LIBRARY_DIRS})
# -D
add_definitions(${CFLAGS} -DLOCALEDIR=\"${LOCALEDIR}\"
-DPACKAGE_VERSION=\"${VERSION}\" -DGETTEXT_PACKAGE=\"${PROJ}\"
-DMINOR_VERSION=\"${MINOR_VERSION}\" -DMID_VERSION=\"${MID_VERSION}\"
-DMAJOR_VERSION=\"${MAJOR_VESION}\")
# -l
target_link_libraries(${PROJ} ${${PROJ}_LIBRARIES} -lm)
# Installation of the program
INSTALL(TARGETS ${PROJ} DESTINATION "bin")

56
cmakelists_/Makefiledbg Normal file
View File

@ -0,0 +1,56 @@
# run `make DEF=...` to add extra defines
PROGRAM :=
<<<<<<< HEAD
LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all
SRCS := $(wildcard *.c)
DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111
OBJDIR := mk
CFLAGS += -O2 -Wall -Wextra -Wno-trampolines -std=gnu99
=======
LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all -Xlinker --warn-common
SRCS := $(wildcard *.c)
DEFINES := $(DEF) -D_XOPEN_SOURCE=1111
OBJDIR := mk
CFLAGS += -O2 -Wall -Werror -Wextra -Wno-trampolines -std=gnu99
>>>>>>> 8c51b1c4c29737d7d3c062d88cbb0f3ca2f97652
OBJS := $(addprefix $(OBJDIR)/, $(SRCS:%.c=%.o))
DEPS := $(OBJS:.o=.d)
CC = gcc
#CXX = g++
all : $(OBJDIR) $(PROGRAM)
<<<<<<< HEAD
debug: CFLAGS += -DEBUG -Werror
debug: all
=======
>>>>>>> 8c51b1c4c29737d7d3c062d88cbb0f3ca2f97652
$(PROGRAM) : $(OBJS)
@echo -e "\t\tLD $(PROGRAM)"
$(CC) $(LDFLAGS) $(OBJS) -o $(PROGRAM)
$(OBJDIR):
mkdir $(OBJDIR)
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif
$(OBJDIR)/%.o: %.c
@echo -e "\t\tCC $<"
$(CC) -MD -c $(LDFLAGS) $(CFLAGS) $(DEFINES) -o $@ $<
clean:
@echo -e "\t\tCLEAN"
@rm -f $(OBJS) $(DEPS)
@rmdir $(OBJDIR) 2>/dev/null || true
xclean: clean
@rm -f $(PROGRAM)
gentags:
CFLAGS="$(CFLAGS) $(DEFINES)" geany -g $(PROGRAM).c.tags *[hc] 2>/dev/null
.PHONY: gentags clean xclean

1
count_bits.c Normal file
View File

@ -0,0 +1 @@
__builtin_popcount(x) - counts all non-zero bits in number

View File

@ -1,6 +1,8 @@
Network daemon snippet
==================
This isn't an end-product, but just a template for different net-daemons.
Open a socket at given port (default: 4444), works with http & direct requests.
Can read and send commands over serial interface.

3
powerof2.c Normal file
View File

@ -0,0 +1,3 @@
int IsPowerOfTwo(uint64_t x){
return (x != 0) && ((x & (x - 1)) == 0);
}

View File

@ -86,14 +86,20 @@ void *handle_socket(void *asock){
buff[readed] = 0;
// DBG("get %zd bytes: %s", readed, buff);
// now we should check what do user want
char *got, *found = buff;
char *found = buff;
DBG("Buff: %s", buff);
if((got = stringscan(buff, "GET")) || (got = stringscan(buff, "POST"))){ // web query
//if((got = stringscan(buff, "GET"))){ // web query
if(strncmp(buff, "GET", 3) == 0){
webquery = 1;
char *slash = strchr(got, '/');
char *slash = strchr(buff, '/');
if(slash) found = slash + 1;
// web query have format GET /some.resource
}else if(strncmp(buff, "POST", 4) == 0){
webquery = 1;
char *hdrend = strstr(buff, "\r\n\r\n");
if(hdrend) found = hdrend + 4;
}
DBG("Found=%s", found);
size_t L;
char *X;
if((X = strstr(found, "sum="))){ // check working for GET from browser
@ -103,18 +109,18 @@ void *handle_socket(void *asock){
newx = x;
DBG("User give sum=%d", x);
}
L = snprintf(obuff, BUFLEN, "sum=%d\n", newx);
int l = snprintf(obuff, BUFLEN, "sum=%d\n", newx);
if(webquery){ // save file with current value
L = snprintf(obuff, BUFLEN,
"HTTP/2.0 200 OK\r\n"
"Access-Control-Allow-Origin: *\r\n"
"Access-Control-Allow-Methods: GET, POST\r\n"
"Access-Control-Allow-Credentials: true\r\n"
"Content-type: multipart/form-data\r\nContent-Length: %zd\r\n\r\n"
"sum=%d\n", L, newx);
}
"Content-type: text/html\r\nContent-Length: %d\r\n\r\n"
"sum=%d\n", l, newx);
}else L = l;
if(L != (size_t)write(sock, obuff, L)) WARN("write");
DBG("%s", obuff);
DBG("\nWRITE TO client: %s\n", obuff);
}else{ // simply copy back all data
size_t blen = strlen(buff);
if(webquery){