From c7b830f136f356e692d7d47606668fe5f2209565 Mon Sep 17 00:00:00 2001 From: Pierre Godicheau Date: Mon, 23 Jan 2023 15:15:51 +0100 Subject: [PATCH 1/9] remove build file --- bin/Debug/gmon.out | Bin 4071 -> 0 bytes bin/Debug/sainsmartrelay | Bin 33497 -> 0 bytes bin/Release/sainsmartrelay | Bin 18984 -> 0 bytes obj/Debug/sainsmartrelay.o | Bin 42832 -> 0 bytes obj/Release/sainsmartrelay.o | Bin 21768 -> 0 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 bin/Debug/gmon.out delete mode 100755 bin/Debug/sainsmartrelay delete mode 100755 bin/Release/sainsmartrelay delete mode 100644 obj/Debug/sainsmartrelay.o delete mode 100644 obj/Release/sainsmartrelay.o diff --git a/bin/Debug/gmon.out b/bin/Debug/gmon.out deleted file mode 100644 index ef6a390f21a7d452a3b4844400f65d48a4c02b49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4071 zcmYe#&Cg?GKm!*99Ka$c^da;Cb_RwNph$6Qa(-S)F<1`7g)v6y(GVC7fzc2c4S~@R z7!85Z5Eu=C(GVC7fzc2c4S~@R7!3j1g#hCMWe2e7t>O?G)RSjC02S;LMhF4`^5+bG diff --git a/bin/Debug/sainsmartrelay b/bin/Debug/sainsmartrelay deleted file mode 100755 index ee80d63474429ab1d8ef1da9af326183fdb620f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33497 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 diff --git a/obj/Debug/sainsmartrelay.o b/obj/Debug/sainsmartrelay.o deleted file mode 100644 index 4f8ab2b14ceac04320cd733d9dfa1c288ec6a5ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42832 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 Ag8%>k From 91fbe78af1343f4e206d4099a80cd79ecad0bf5a Mon Sep 17 00:00:00 2001 From: Pierre Godicheau Date: Mon, 23 Jan 2023 15:26:34 +0100 Subject: [PATCH 2/9] remove add .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2423241 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +bin/ +obj/ +checks.json From 27d0bc148cf84585bf659cab6d7337c077a5e601 Mon Sep 17 00:00:00 2001 From: Pierre Godicheau Date: Mon, 23 Jan 2023 15:50:36 +0100 Subject: [PATCH 3/9] add udev rule ex --- README.md | 10 ++++++---- udev/53-ftdi.rules | 3 +++ 2 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 udev/53-ftdi.rules diff --git a/README.md b/README.md index 6a3696d..af0c902 100644 --- a/README.md +++ b/README.md @@ -17,18 +17,20 @@ This software is based on C program and requires gcc to compile the program from cd sainsmart-usb-relay make sudo make install - + The "make install" command copies the binary to /usr/local/bin. So the command can be utilized anywhere from the system. - The following works for both a Raspberry Pi (Debian Wheezy) and Ubuntu 16.04, getting ordinary users (e.g. ‘pi’ on the RPi) access to the FTDI device without needing root permissions: - Create a file /etc/udev/rules.d/99-libftdi.rules. You will need sudo access to create this file. + Create a file /etc/udev/rules.d/53-libftdi.rules. You will need sudo access to create this file. Put the following in the file: SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", GROUP="dialout", MODE="0660" SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", GROUP="dialout", MODE="0660" Some FTDI devices may use other USB PIDs. You could try removing the match on idProduct altogether, just matching on the FTDI vendor ID. Or Use lsusb or similar to determine the exact values to use (or try checking dmesg output on device insertion / removal). - + + See `udev/53-ftdi.rules` for example + Usage ============ This project provides a simple command to interact with the USB relay. @@ -67,4 +69,4 @@ The Sainsmart card uses the FTDI FT245RL chip. This chip is controlled directly To prevent automatic loading of the driver, add the following line to /etc/modprobe.d/blacklist.conf: blacklist ftdi_sio -Both 4 and 8 channel versions are supported. However, there seems to be no way to automatically detect which version of the card is used. Therefore the number of relay channles can be configured in the configuration file. +Both 4 and 8 channel versions are supported. However, there seems to be no way to automatically detect which version of the card is used. Therefore the number of relay channles can be configured in the configuration file. diff --git a/udev/53-ftdi.rules b/udev/53-ftdi.rules new file mode 100644 index 0000000..0102c2d --- /dev/null +++ b/udev/53-ftdi.rules @@ -0,0 +1,3 @@ +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", GROUP="dialout", MODE="0660" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", GROUP="dialout", MODE="0660" + From 3a7eda5215f8f1b568994901556ca9e8e2e29650 Mon Sep 17 00:00:00 2001 From: Pierre Godicheau Date: Thu, 13 Jun 2024 07:50:12 +0200 Subject: [PATCH 4/9] open only FTDI model: 'FT245R USB FIFO', which is that of the Saintsmart boards --- sainsmartrelay.c | 51 +++++++++++++++++++++++++++++++++++------------- sainsmartrelay.h | 1 + 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/sainsmartrelay.c b/sainsmartrelay.c index 8624deb..f69347c 100644 --- a/sainsmartrelay.c +++ b/sainsmartrelay.c @@ -10,6 +10,16 @@ #include "sainsmartrelay.h" +#define ANSI_COLOR_RED "\x1b[31m" +#define ANSI_COLOR_GREEN "\x1b[32m" +#define ANSI_COLOR_RESET "\x1b[0m" + +#define MAX_STR_LEN_MANUFACTURER 128 +#define MAX_STR_LEN_DESCRIPTION 128 +#define MAX_STR_LEN_SERIAL 128 +#define MAX_STR_LEN_SAINSMARTBOARD 4 + + static struct ftdi_context *ftdi; static uint8 g_num_relays=MAX_NUM_RELAYS; @@ -211,9 +221,11 @@ int detect_relay_card_sainsmart_4_8chan(char* portname, uint8* num_relays) return -1; } - /* Try to open FTDI USB device */ - if ((ftdi_usb_open(ftdi, VENDOR_ID, DEVICE_ID)) < 0) + /* Try to open FTDI USB device for sainsmart + relay card with description = SAINSMART_FTDI_CHIP_MODEL ("FT245R USB FIFO") */ + if (ftdi_usb_open_desc(ftdi, VENDOR_ID, DEVICE_ID, SAINSMART_FTDI_CHIP_MODEL,NULL) < 0) { + fprintf(stderr, "unable to open ftdi device: (%s)\n", ftdi_get_error_string(ftdi)); ftdi_free(ftdi); return -1; } @@ -261,39 +273,50 @@ int detect_relay_card_sainsmart_4_8chan(char* portname, uint8* num_relays) *********************************************************/ int find_device(void) { - int ret, i; + int ret; struct ftdi_context *ftdi; struct ftdi_device_list *devlist, *curdev; - char manufacturer[128], description[128]; + char manufacturer[MAX_STR_LEN_MANUFACTURER], description[MAX_STR_LEN_DESCRIPTION], serial[MAX_STR_LEN_SERIAL], sainsmartboard[MAX_STR_LEN_SAINSMARTBOARD]; int retval = EXIT_SUCCESS; + memset(manufacturer, 0, sizeof(manufacturer)); + memset(description, 0, sizeof(description)); + memset(serial, 0, sizeof(serial)); + if ((ftdi = ftdi_new()) == 0) { fprintf(stderr, "ftdi_new failed\n"); return EXIT_FAILURE; } - if ((ret = ftdi_usb_find_all(ftdi, &devlist, 0, 0)) < 0) + if ((ret = ftdi_usb_find_all(ftdi, &devlist, VENDOR_ID, DEVICE_ID)) < 0) { fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n", ret, ftdi_get_error_string(ftdi)); retval = EXIT_FAILURE; goto do_deinit; } - printf("Number of FTDI devices found: %d\n", ret); - i = 0; - for (curdev = devlist; curdev != NULL; i++) - { - printf("Checking device: %d\n", i); - if ((ret = ftdi_usb_get_strings(ftdi, curdev->dev, manufacturer, 128, description, 128, NULL, 0)) < 0) - { + // Iterate through the devices + for (curdev = devlist; curdev != NULL; curdev = curdev->next) { + if ((ret = ftdi_usb_get_strings(ftdi, curdev->dev, manufacturer, MAX_STR_LEN_MANUFACTURER, description, MAX_STR_LEN_DESCRIPTION, serial, MAX_STR_LEN_SERIAL)) < 0) { fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", ret, ftdi_get_error_string(ftdi)); retval = EXIT_FAILURE; goto done; } - printf("Manufacturer: %s, Description: %s\n", manufacturer, description); - curdev = curdev->next; + if (0 == strncmp(description, SAINSMART_FTDI_CHIP_MODEL, strlen(SAINSMART_FTDI_CHIP_MODEL))) + { + snprintf(sainsmartboard, sizeof(sainsmartboard), "%s", "YES"); + printf("Manufacturer: %-8s, Description: %-20s, Serial: %-20s, Sainsmart Board: %s%s%s\n", + manufacturer, description, serial, ANSI_COLOR_GREEN, sainsmartboard, ANSI_COLOR_RESET); + } + else + { + snprintf(sainsmartboard, sizeof(sainsmartboard), "%s", "NO"); + printf("Manufacturer: %-8s, Description: %-20s, Serial: %-20s, Sainsmart Board: %s%s%s\n", + manufacturer, description, serial, ANSI_COLOR_RED, sainsmartboard, ANSI_COLOR_RESET); + } + } done: ftdi_list_free(&devlist); diff --git a/sainsmartrelay.h b/sainsmartrelay.h index 930368c..1af449f 100644 --- a/sainsmartrelay.h +++ b/sainsmartrelay.h @@ -3,6 +3,7 @@ #define VENDOR_ID 0x0403 #define DEVICE_ID 0x6001 +#define SAINSMART_FTDI_CHIP_MODEL "FT245R USB FIFO" #define FIRST_RELAY 1 #define MAX_NUM_RELAYS 4 From 08225fe4f45dfecbd55c26a1d33c57da6e6ee237 Mon Sep 17 00:00:00 2001 From: Pierre Godicheau Date: Thu, 13 Jun 2024 07:55:52 +0200 Subject: [PATCH 5/9] add clang format --- .clang-format | 238 +++++++++++++++++++++++ sainsmartrelay.c | 497 +++++++++++++++++++++++------------------------ sainsmartrelay.h | 28 ++- 3 files changed, 492 insertions(+), 271 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..95239ac --- /dev/null +++ b/.clang-format @@ -0,0 +1,238 @@ +# DO NOT EDIT +# USE https://clang-format-configurator.site/ +# Use version 17.0.6 + +--- +BasedOnStyle: Microsoft +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseColons: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: false + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAfterAttributes: Never +BreakAfterJavaFieldAnnotations: true +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Allman +BreakBeforeConceptDeclarations: Always +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +ColumnLimit: 0 +CommentPragmas: "^ IWYU pragma:" +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: ^"(llvm|llvm-c|clang|clang-c)/ + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: ^(<|"(gtest|gmock|isl|json)/) + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: .* + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: (Test)?$ +IncludeIsMainSourceRegex: "" +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: true +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: BeforeHash +IndentRequiresClause: true +IndentWidth: 4 +IndentWrappedFunctionNames: true +InsertBraces: true +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtEOF: false +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +Language: Cpp +LineEnding: DeriveLF +MacroBlockBegin: "" +MacroBlockEnd: "" +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PPIndentWidth: -1 +PackConstructorInitializers: BinPack +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 1000 +PointerAlignment: Left +QualifierAlignment: Leave +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: Never +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDeclarationName: false + AfterFunctionDefinitionName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + InConditionalStatements: false + InCStyleCasts: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseTab: Never +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE diff --git a/sainsmartrelay.c b/sainsmartrelay.c index f69347c..7a758c5 100644 --- a/sainsmartrelay.c +++ b/sainsmartrelay.c @@ -9,21 +9,19 @@ #include "sainsmartrelay.h" +#define ANSI_COLOR_RED "\x1b[31m" +#define ANSI_COLOR_GREEN "\x1b[32m" +#define ANSI_COLOR_RESET "\x1b[0m" -#define ANSI_COLOR_RED "\x1b[31m" -#define ANSI_COLOR_GREEN "\x1b[32m" -#define ANSI_COLOR_RESET "\x1b[0m" +#define MAX_STR_LEN_MANUFACTURER 128 +#define MAX_STR_LEN_DESCRIPTION 128 +#define MAX_STR_LEN_SERIAL 128 +#define MAX_STR_LEN_SAINSMARTBOARD 4 -#define MAX_STR_LEN_MANUFACTURER 128 -#define MAX_STR_LEN_DESCRIPTION 128 -#define MAX_STR_LEN_SERIAL 128 -#define MAX_STR_LEN_SAINSMARTBOARD 4 +static struct ftdi_context* ftdi; +static uint8 g_num_relays = MAX_NUM_RELAYS; - -static struct ftdi_context *ftdi; -static uint8 g_num_relays=MAX_NUM_RELAYS; - -static void usage(char *myName) +static void usage(char* myName) { fprintf(stderr, "\nUsage:\n"); fprintf(stderr, " %s --on [1|2|3|4|all]\n", myName); @@ -33,7 +31,7 @@ static void usage(char *myName) fprintf(stderr, " %s -h\n", myName); } -static void help(char *myName) +static void help(char* myName) { fprintf(stdout, "\nHelp:\n %s --on [1|2|3|4|all] | --off [1|2|3|4|all] | --status | --findall | [-h]\n", myName); fprintf(stdout, " --help|-h print this help.\n"); @@ -45,16 +43,14 @@ static void help(char *myName) static void checkPermission() { - if(geteuid() != 0) + if (geteuid() != 0) { - fprintf(stderr,"\nWarning:\n this program is currently not running with root priviledges !\n"); - fprintf(stderr,"Therefore it might not be able to access your relay cards communication port.\n"); - fprintf(stderr,"Consider invoking the program from the root account or use \"sudo ...\"\n"); + fprintf(stderr, "\nWarning:\n this program is currently not running with root priviledges !\n"); + fprintf(stderr, "Therefore it might not be able to access your relay cards communication port.\n"); + fprintf(stderr, "Consider invoking the program from the root account or use \"sudo ...\"\n"); } } - - /********************************************************** * Function strsplit() * @@ -66,21 +62,21 @@ static void checkPermission() * * Return: array - response array *********************************************************/ -char **strsplit(const char* str, const char* delim, size_t* numtokens) +char** strsplit(const char* str, const char* delim, size_t* numtokens) { // copy the original string so that we don't overwrite parts of it // (don't do this if you don't need to keep the old line, // as this is less efficient) - char *s = strdup(str); + char* s = strdup(str); // these three variables are part of a very common idiom to // implement a dynamically-growing array size_t tokens_alloc = 1; - size_t tokens_used = 0; - char **tokens = calloc(tokens_alloc, sizeof(char*)); + size_t tokens_used = 0; + char** tokens = calloc(tokens_alloc, sizeof(char*)); char *token, *strtok_ctx; for (token = strtok_r(s, delim, &strtok_ctx); - token != NULL; - token = strtok_r(NULL, delim, &strtok_ctx)) + token != NULL; + token = strtok_r(NULL, delim, &strtok_ctx)) { // check if we need to allocate more space for tokens if (tokens_used == tokens_alloc) @@ -105,7 +101,6 @@ char **strsplit(const char* str, const char* delim, size_t* numtokens) return tokens; } - /********************************************************** * Function remove_duplicate() * @@ -117,23 +112,22 @@ char **strsplit(const char* str, const char* delim, size_t* numtokens) * * Return: array - New array with deduped array content *********************************************************/ -int *remove_duplicate(int array[],int length, size_t* numtokens) +int* remove_duplicate(int array[], int length, size_t* numtokens) { size_t tokens_alloc = 1; - size_t tokens_used = 0; - int *tokens = calloc(tokens_alloc, sizeof(int*)); + size_t tokens_used = 0; + int* tokens = calloc(tokens_alloc, sizeof(int*)); - int *current , *end = array + length - 1; + int *current, *end = array + length - 1; int flag = 0; - for ( current = array + 1; array < end; array++, current = array + 1 ) + for (current = array + 1; array < end; array++, current = array + 1) { flag = 0; - while ( current <= end ) + while (current <= end) { - if ( *current == *array ) + if (*current == *array) { *current = *end--; - } else { @@ -141,7 +135,7 @@ int *remove_duplicate(int array[],int length, size_t* numtokens) current++; } } - if(flag == 1) + if (flag == 1) { if (tokens_used == tokens_alloc) { @@ -182,17 +176,17 @@ int *remove_duplicate(int array[],int length, size_t* numtokens) * * Return: array of relay id and it's status *********************************************************/ -int *get_bits(int n, int bitswanted) +int* get_bits(int n, int bitswanted) { - int *bits = malloc(sizeof(int) * bitswanted); + int* bits = malloc(sizeof(int) * bitswanted); int k; - for(k=0; k> k; - bits[k] = thebit; + int thebit = masked_n >> k; + bits[k] = thebit; } return bits; @@ -223,7 +217,7 @@ int detect_relay_card_sainsmart_4_8chan(char* portname, uint8* num_relays) /* Try to open FTDI USB device for sainsmart relay card with description = SAINSMART_FTDI_CHIP_MODEL ("FT245R USB FIFO") */ - if (ftdi_usb_open_desc(ftdi, VENDOR_ID, DEVICE_ID, SAINSMART_FTDI_CHIP_MODEL,NULL) < 0) + if (ftdi_usb_open_desc(ftdi, VENDOR_ID, DEVICE_ID, SAINSMART_FTDI_CHIP_MODEL, NULL) < 0) { fprintf(stderr, "unable to open ftdi device: (%s)\n", ftdi_get_error_string(ftdi)); ftdi_free(ftdi); @@ -239,10 +233,10 @@ int detect_relay_card_sainsmart_4_8chan(char* portname, uint8* num_relays) } /* Check if this is an R type chip - * Type 245RL = 5000 - */ - //printf("relay type:%d\n",ftdi->type); - if (ftdi->type != 5000 && ftdi->type != TYPE_R ) + * Type 245RL = 5000 + */ + // printf("relay type:%d\n",ftdi->type); + if (ftdi->type != 5000 && ftdi->type != TYPE_R) { fprintf(stderr, "unable to continue, not an R-type chip\n"); ftdi_free(ftdi); @@ -253,15 +247,17 @@ int detect_relay_card_sainsmart_4_8chan(char* portname, uint8* num_relays) ftdi_read_chipid(ftdi, &chipid); /* Return parameters */ - if (num_relays!=NULL) *num_relays = g_num_relays; + if (num_relays != NULL) + { + *num_relays = g_num_relays; + } sprintf(portname, "FTDI chipid %X", chipid); - //printf("DBG: portname %s\n", portname); + // printf("DBG: portname %s\n", portname); ftdi_usb_close(ftdi); return 0; } - /********************************************************** * Function find_device() * @@ -274,7 +270,7 @@ int detect_relay_card_sainsmart_4_8chan(char* portname, uint8* num_relays) int find_device(void) { int ret; - struct ftdi_context *ftdi; + struct ftdi_context* ftdi; struct ftdi_device_list *devlist, *curdev; char manufacturer[MAX_STR_LEN_MANUFACTURER], description[MAX_STR_LEN_DESCRIPTION], serial[MAX_STR_LEN_SERIAL], sainsmartboard[MAX_STR_LEN_SAINSMARTBOARD]; int retval = EXIT_SUCCESS; @@ -292,14 +288,16 @@ int find_device(void) if ((ret = ftdi_usb_find_all(ftdi, &devlist, VENDOR_ID, DEVICE_ID)) < 0) { fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n", ret, ftdi_get_error_string(ftdi)); - retval = EXIT_FAILURE; + retval = EXIT_FAILURE; goto do_deinit; } printf("Number of FTDI devices found: %d\n", ret); // Iterate through the devices - for (curdev = devlist; curdev != NULL; curdev = curdev->next) { - if ((ret = ftdi_usb_get_strings(ftdi, curdev->dev, manufacturer, MAX_STR_LEN_MANUFACTURER, description, MAX_STR_LEN_DESCRIPTION, serial, MAX_STR_LEN_SERIAL)) < 0) { + for (curdev = devlist; curdev != NULL; curdev = curdev->next) + { + if ((ret = ftdi_usb_get_strings(ftdi, curdev->dev, manufacturer, MAX_STR_LEN_MANUFACTURER, description, MAX_STR_LEN_DESCRIPTION, serial, MAX_STR_LEN_SERIAL)) < 0) + { fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", ret, ftdi_get_error_string(ftdi)); retval = EXIT_FAILURE; goto done; @@ -308,15 +306,14 @@ int find_device(void) { snprintf(sainsmartboard, sizeof(sainsmartboard), "%s", "YES"); printf("Manufacturer: %-8s, Description: %-20s, Serial: %-20s, Sainsmart Board: %s%s%s\n", - manufacturer, description, serial, ANSI_COLOR_GREEN, sainsmartboard, ANSI_COLOR_RESET); + manufacturer, description, serial, ANSI_COLOR_GREEN, sainsmartboard, ANSI_COLOR_RESET); } else { - snprintf(sainsmartboard, sizeof(sainsmartboard), "%s", "NO"); - printf("Manufacturer: %-8s, Description: %-20s, Serial: %-20s, Sainsmart Board: %s%s%s\n", - manufacturer, description, serial, ANSI_COLOR_RED, sainsmartboard, ANSI_COLOR_RESET); + snprintf(sainsmartboard, sizeof(sainsmartboard), "%s", "NO"); + printf("Manufacturer: %-8s, Description: %-20s, Serial: %-20s, Sainsmart Board: %s%s%s\n", + manufacturer, description, serial, ANSI_COLOR_RED, sainsmartboard, ANSI_COLOR_RESET); } - } done: ftdi_list_free(&devlist); @@ -340,7 +337,7 @@ int get_relay_sainsmart_4_8chan(uint8 relay, relay_state_t* relay_state) { unsigned char buf[1]; - if (relay(FIRST_RELAY+g_num_relays-1)) + if (relay < FIRST_RELAY || relay > (FIRST_RELAY + g_num_relays - 1)) { fprintf(stderr, "ERROR: Relay number out of range\n"); return -1; @@ -357,13 +354,13 @@ int get_relay_sainsmart_4_8chan(uint8 relay, relay_state_t* relay_state) /* Get relay state from the card */ if (ftdi_read_pins(ftdi, &buf[0]) < 0) { - fprintf(stderr,"read failed for 0x%x, error %s\n",buf[0], ftdi_get_error_string(ftdi)); + fprintf(stderr, "read failed for 0x%x, error %s\n", buf[0], ftdi_get_error_string(ftdi)); return -3; } - //printf("DBG: Read GPIO bits %02X\n", buf[0]); - int *bits = get_bits(buf[0], g_num_relays); + // printf("DBG: Read GPIO bits %02X\n", buf[0]); + int* bits = get_bits(buf[0], g_num_relays); - relay = relay-1; + relay = relay - 1; *relay_state = (bits[relay] > 0) ? ON : OFF; ftdi_usb_close(ftdi); @@ -380,7 +377,7 @@ int get_relay_sainsmart_4_8chan(uint8 relay, relay_state_t* relay_state) * Return: 0 - success * < 0 - fail *********************************************************/ -int get_relay_sainsmart_4_8chan_all(int *relay_states) +int get_relay_sainsmart_4_8chan_all(int* relay_states) { unsigned char buf[1]; @@ -395,16 +392,16 @@ int get_relay_sainsmart_4_8chan_all(int *relay_states) /* Get relay state from the card */ if (ftdi_read_pins(ftdi, &buf[0]) < 0) { - fprintf(stderr,"read failed for 0x%x, error %s\n",buf[0], ftdi_get_error_string(ftdi)); + fprintf(stderr, "read failed for 0x%x, error %s\n", buf[0], ftdi_get_error_string(ftdi)); return -3; } - //printf("DBG: Read GPIO bits %02X\n", buf[0]); - int *bits = get_bits(buf[0], g_num_relays); + // printf("DBG: Read GPIO bits %02X\n", buf[0]); + int* bits = get_bits(buf[0], g_num_relays); int j; - for(j=0; j(FIRST_RELAY+g_num_relays-1)) + if (relay < FIRST_RELAY || relay > (FIRST_RELAY + g_num_relays - 1)) { fprintf(stderr, "ERROR: Relay number out of range\n"); return -1; @@ -476,29 +473,29 @@ int set_relay_sainsmart_4_8chan(uint8 relay, relay_state_t relay_state) /* Get relay state from the card */ if (ftdi_read_pins(ftdi, buf) < 0) { - fprintf(stderr,"read failed for 0x%x, error %s\n",buf[0], ftdi_get_error_string(ftdi)); + fprintf(stderr, "read failed for 0x%x, error %s\n", buf[0], ftdi_get_error_string(ftdi)); return -3; } /* Set the new relay state bit */ - relay = relay-1; + relay = relay - 1; if (relay_state == OFF) { /* Clear the relay bit in mask */ - buf[0] = buf[0] & ~(0x01< 0) ? "ON" : "OFF"); + int j; + for (j = 0; j < g_num_relays; j++) + { + fprintf(stdout, "%d: %s\n", j + 1, (relay_states[j] > 0) ? "ON" : "OFF"); + } + exit(EXIT_SUCCESS); } - exit(EXIT_SUCCESS); } - } - else if(isdigit(optarg[0])) - { - if (get_relay_sainsmart_4_8chan(atoi(optarg), &rstate) == 0) + else if (isdigit(optarg[0])) { - fprintf(stdout, "%d: %s\n", atoi(optarg),(rstate==ON) ? "ON" : "OFF"); - exit(EXIT_SUCCESS); + if (get_relay_sainsmart_4_8chan(atoi(optarg), &rstate) == 0) + { + fprintf(stdout, "%d: %s\n", atoi(optarg), (rstate == ON) ? "ON" : "OFF"); + exit(EXIT_SUCCESS); + } } - } - else - { - fprintf(stderr, "invalid value is set to --status argument\n"); + else + { + fprintf(stderr, "invalid value is set to --status argument\n"); + exit(EXIT_FAILURE); + } + break; + case 'h': + help(argv[0]); + exit(EXIT_SUCCESS); + break; + case ':': + fprintf(stderr, "%s: option `-%c' requires an argument\n", argv[0], optopt); exit(EXIT_FAILURE); - } - break; - case 'h' : - help(argv[0]); - exit(EXIT_SUCCESS); - break; - case ':': - fprintf(stderr, "%s: option `-%c' requires an argument\n",argv[0], optopt); - exit(EXIT_FAILURE); - break; - case '?': - /* getopt_long already printed an error message. */ - break; + break; + case '?': + /* getopt_long already printed an error message. */ + break; - default: - usage(argv[0]); - exit(EXIT_FAILURE); + default: + usage(argv[0]); + exit(EXIT_FAILURE); } } - - char **op_relay_list = {0}; - size_t numtokens = 0; - int i = 0; - size_t numtok = 0; - int *relays; + char** op_relay_list = {0}; + size_t numtokens = 0; + int i = 0; + size_t numtok = 0; + int* relays; /* - * Get the current status of the relay - */ + * Get the current status of the relay + */ uint8 relay_data; if (get_relay_sainsmart_4_8chan_raw(&relay_data) != 0) { @@ -780,23 +773,22 @@ int main(int argc, char *argv[]) } /* - * Process all the multiple relay ON state operation - */ + * Process all the multiple relay ON state operation + */ - if(opOn == ID_ON_ALL) + if (opOn == ID_ON_ALL) { - for(i=1; i<= g_num_relays; i++) + for (i = 1; i <= g_num_relays; i++) { - relay_data = relay_data | (0x01<<(i-1)); - + relay_data = relay_data | (0x01 << (i - 1)); } } - else if(opOn == ID_ON) + else if (opOn == ID_ON) { - relay_data = relay_data | (0x01<<(atoi(op_relay_on)-1)); + relay_data = relay_data | (0x01 << (atoi(op_relay_on) - 1)); } - else if(opOn == ID_ON_MULTIPLE) + else if (opOn == ID_ON_MULTIPLE) { op_relay_list = strsplit(op_relay_on, ", \t\n", &numtokens); @@ -806,37 +798,33 @@ int main(int argc, char *argv[]) relay_list[i] = atoi(strdup(op_relay_list[i])); free(op_relay_list[i]); } - relays = remove_duplicate(relay_list,numtokens,&numtok); + relays = remove_duplicate(relay_list, numtokens, &numtok); - for(i=0; i< numtok; i++) + for (i = 0; i < numtok; i++) { - if(relays[i] != 0) + if (relays[i] != 0) { - relay_data = relay_data | (0x01<<(relays[i]-1)); + relay_data = relay_data | (0x01 << (relays[i] - 1)); } - } - - } /* - * Process all the multiple relay OFF state operation - */ - if(opOff == ID_OFF_ALL) + * Process all the multiple relay OFF state operation + */ + if (opOff == ID_OFF_ALL) { - for(i=1; i<= g_num_relays; i++) + for (i = 1; i <= g_num_relays; i++) { - relay_data = relay_data & ~(0x01<<(i-1)); - + relay_data = relay_data & ~(0x01 << (i - 1)); } } - else if(opOff == ID_OFF) + else if (opOff == ID_OFF) { - relay_data = relay_data & ~(0x01<<(atoi(op_relay_off)-1)); + relay_data = relay_data & ~(0x01 << (atoi(op_relay_off) - 1)); } - else if(opOff == ID_OFF_MULTIPLE) + else if (opOff == ID_OFF_MULTIPLE) { op_relay_list = strsplit(op_relay_off, ", \t\n", &numtokens); int relay_list[numtokens]; @@ -845,31 +833,31 @@ int main(int argc, char *argv[]) relay_list[i] = atoi(strdup(op_relay_list[i])); free(op_relay_list[i]); } - relays = remove_duplicate(relay_list,numtokens,&numtok); + relays = remove_duplicate(relay_list, numtokens, &numtok); - for(i=0; i< numtok; i++) + for (i = 0; i < numtok; i++) { - if(relays[i] != 0) + if (relays[i] != 0) { - relay_data = relay_data & ~(0x01<<(relays[i]-1)); + relay_data = relay_data & ~(0x01 << (relays[i] - 1)); } } } /* - * Write the final state data into the relay - */ - if(opOn != -1 || opOff != -1) + * Write the final state data into the relay + */ + if (opOn != -1 || opOff != -1) { if (set_relay_sainsmart_4_8chan_write(relay_data) == 0) { - int relay_states[g_num_relays-1]; + int relay_states[g_num_relays - 1]; if (get_relay_sainsmart_4_8chan_all(relay_states) == 0) { int j; - for(j=0; j 0) ? "ON" : "OFF"); + fprintf(stdout, "%d: %s\n", j + 1, (relay_states[j] > 0) ? "ON" : "OFF"); } exit(EXIT_SUCCESS); } @@ -879,9 +867,6 @@ int main(int argc, char *argv[]) fprintf(stderr, "Error writing data to the relay.\n"); exit(EXIT_FAILURE); } - - } exit(EXIT_SUCCESS); } - diff --git a/sainsmartrelay.h b/sainsmartrelay.h index 1af449f..04e0387 100644 --- a/sainsmartrelay.h +++ b/sainsmartrelay.h @@ -1,27 +1,26 @@ #ifndef sainsmartrelay_h #define sainsmartrelay_h -#define VENDOR_ID 0x0403 -#define DEVICE_ID 0x6001 +#define VENDOR_ID 0x0403 +#define DEVICE_ID 0x6001 #define SAINSMART_FTDI_CHIP_MODEL "FT245R USB FIFO" -#define FIRST_RELAY 1 -#define MAX_NUM_RELAYS 4 +#define FIRST_RELAY 1 +#define MAX_NUM_RELAYS 4 #define MAX_RELAY_CARD_NAME_LEN 40 -#define MAX_COM_PORT_NAME_LEN 32 +#define MAX_COM_PORT_NAME_LEN 32 -typedef unsigned char uint8; +typedef unsigned char uint8; typedef unsigned short uint16; -typedef unsigned long uint32; +typedef unsigned long uint32; typedef enum { - OFF=0, - ON, - PULSE, - INVALID -} -relay_state_t; + OFF = 0, + ON, + PULSE, + INVALID +} relay_state_t; typedef enum { @@ -33,7 +32,6 @@ typedef enum ID_OFF_MULTIPLE, ID_GET, ID_GET_ALL -} -operations; +} operations; #endif From 6be9b51b7e6f02238b9dc8e17f4e957f1311b63f Mon Sep 17 00:00:00 2001 From: Pierre Godicheau Date: Thu, 13 Jun 2024 08:32:24 +0200 Subject: [PATCH 6/9] open only FTDI model: 'FT245R USB FIFO', which is that of the Saintsmart boards --- sainsmartrelay.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sainsmartrelay.c b/sainsmartrelay.c index 7a758c5..27a7a6c 100644 --- a/sainsmartrelay.c +++ b/sainsmartrelay.c @@ -344,7 +344,7 @@ int get_relay_sainsmart_4_8chan(uint8 relay, relay_state_t* relay_state) } /* Open FTDI USB device */ - if ((ftdi_usb_open(ftdi, VENDOR_ID, DEVICE_ID)) < 0) + if ((ftdi_usb_open_desc(ftdi, VENDOR_ID, DEVICE_ID, SAINSMART_FTDI_CHIP_MODEL, NULL)) < 0) { fprintf(stderr, "unable to open ftdi device: (%s)\n", ftdi_get_error_string(ftdi)); ftdi_free(ftdi); @@ -382,7 +382,7 @@ int get_relay_sainsmart_4_8chan_all(int* relay_states) unsigned char buf[1]; /* Open FTDI USB device */ - if ((ftdi_usb_open(ftdi, VENDOR_ID, DEVICE_ID)) < 0) + if ((ftdi_usb_open_desc(ftdi, VENDOR_ID, DEVICE_ID, SAINSMART_FTDI_CHIP_MODEL, NULL)) < 0) { fprintf(stderr, "unable to open ftdi device: (%s)\n", ftdi_get_error_string(ftdi)); ftdi_free(ftdi); @@ -422,7 +422,7 @@ int get_relay_sainsmart_4_8chan_raw(uint8* relay_data) unsigned char buf[1]; /* Open FTDI USB device */ - if ((ftdi_usb_open(ftdi, VENDOR_ID, DEVICE_ID)) < 0) + if ((ftdi_usb_open_desc(ftdi, VENDOR_ID, DEVICE_ID, SAINSMART_FTDI_CHIP_MODEL, NULL)) < 0) { fprintf(stderr, "unable to open ftdi device: (%s)\n", ftdi_get_error_string(ftdi)); ftdi_free(ftdi); @@ -463,7 +463,7 @@ int set_relay_sainsmart_4_8chan(uint8 relay, relay_state_t relay_state) } /* Open FTDI USB device */ - if ((ftdi_usb_open(ftdi, VENDOR_ID, DEVICE_ID)) < 0) + if ((ftdi_usb_open_desc(ftdi, VENDOR_ID, DEVICE_ID, SAINSMART_FTDI_CHIP_MODEL, NULL)) < 0) { fprintf(stderr, "unable to open ftdi device: (%s)\n", ftdi_get_error_string(ftdi)); ftdi_free(ftdi); @@ -519,7 +519,7 @@ int set_relay_sainsmart_4_8chan_all(relay_state_t relay_state) int i; /* Open FTDI USB device */ - if ((ftdi_usb_open(ftdi, VENDOR_ID, DEVICE_ID)) < 0) + if ((ftdi_usb_open_desc(ftdi, VENDOR_ID, DEVICE_ID, SAINSMART_FTDI_CHIP_MODEL, NULL)) < 0) { fprintf(stderr, "unable to open ftdi device: (%s)\n", ftdi_get_error_string(ftdi)); ftdi_free(ftdi); @@ -581,7 +581,7 @@ int set_relay_sainsmart_4_8chan_write(uint8 relay_data) unsigned char buf[1]; /* Open FTDI USB device */ - if ((ftdi_usb_open(ftdi, VENDOR_ID, DEVICE_ID)) < 0) + if ((ftdi_usb_open_desc(ftdi, VENDOR_ID, DEVICE_ID, SAINSMART_FTDI_CHIP_MODEL, NULL)) < 0) { fprintf(stderr, "unable to open ftdi device: (%s)\n", ftdi_get_error_string(ftdi)); ftdi_free(ftdi); From adefa49810aa9548346e464ada1ccc3063afc43c Mon Sep 17 00:00:00 2001 From: Pierre Godicheau Date: Thu, 13 Jun 2024 09:06:28 +0200 Subject: [PATCH 7/9] update doc --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index af0c902..3dd7a85 100644 --- a/README.md +++ b/README.md @@ -37,29 +37,29 @@ This project provides a simple command to interact with the USB relay. To turn on the USB relay - sudo sainsmart --on RELAY_NUMBER + sudo sainsmartrelay --on RELAY_NUMBER For example to turn on the relay 1 we can use - sudo sainsmart --on 1 + sudo sainsmartrelay --on 1 To run on all the relays - sudo sainsmart --on all + sudo sainsmartrelay --on all To turn off the USB relay 1 - sudo sainsmart --off 1 + sudo sainsmartrelay --off 1 To run on all the relays - sudo sainsmart --off all + sudo sainsmartrelay --off all To get the status of the relays - sudo sainsmart --status + sudo sainsmartrelay --status To get more help information - sudo sainsmart --help + sudo sainsmartrelay --help Notes ============ From d51f9f44f7ee7c5c012f5bb027c7b66f9930eef6 Mon Sep 17 00:00:00 2001 From: Pierre Godicheau Date: Thu, 13 Jun 2024 11:57:52 +0200 Subject: [PATCH 8/9] typo --- sainsmartrelay.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sainsmartrelay.c b/sainsmartrelay.c index 27a7a6c..3464e01 100644 --- a/sainsmartrelay.c +++ b/sainsmartrelay.c @@ -305,13 +305,13 @@ int find_device(void) if (0 == strncmp(description, SAINSMART_FTDI_CHIP_MODEL, strlen(SAINSMART_FTDI_CHIP_MODEL))) { snprintf(sainsmartboard, sizeof(sainsmartboard), "%s", "YES"); - printf("Manufacturer: %-8s, Description: %-20s, Serial: %-20s, Sainsmart Board: %s%s%s\n", + printf("Manufacturer: %-6s, Description: %-20s, Serial: %-10s, Sainsmart Board: %s%s%s\n", manufacturer, description, serial, ANSI_COLOR_GREEN, sainsmartboard, ANSI_COLOR_RESET); } else { snprintf(sainsmartboard, sizeof(sainsmartboard), "%s", "NO"); - printf("Manufacturer: %-8s, Description: %-20s, Serial: %-20s, Sainsmart Board: %s%s%s\n", + printf("Manufacturer: %-6s, Description: %-20s, Serial: %-10s, Sainsmart Board: %s%s%s\n", manufacturer, description, serial, ANSI_COLOR_RED, sainsmartboard, ANSI_COLOR_RESET); } } From 938ff56a5e27b2489c43cdf2b64ddac85dade2a7 Mon Sep 17 00:00:00 2001 From: Pierre Godicheau Date: Fri, 21 Jun 2024 08:24:12 +0200 Subject: [PATCH 9/9] update ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2423241..e6e4034 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ bin/ obj/ checks.json +gmon.out