/*---------------------------------------------------------------------------- (c) TCTEC Pty Ltd www.tctec.net lrelayset (Linux Relay Set) Super4 Relay module control application. dll linking code copied from example at http:/www.ibm.com/developerworks/linux/library/l-dll.html Code created with "Geany" IDE on Puppy Linux Compiled with: gcc -Wall -c "%f" Built with: gcc -Wall -ldl "%f" 10-12-2007 Version 1.0 Created ----------------------------------------------------------------------------*/ #include #include #include #include #include #define VERSION_STRING ("lrelayset Version 1.0") //#define DEBUG (1) void *FunctionLib; /* handle to shared lib file */ uint32_t (*Function)(); /* Pointer to loaded routine */ const char *dlError; /* Pointer to error string */ // FTDI constants // const uint32_t FT_LIST_NUMBER_ONLY = 0x80000000 ; const uint32_t FT_LIST_BY_INDEX = 0x40000000 ; const uint32_t FT_LIST_ALL = 0x20000000 ; const uint32_t FT_OPEN_BY_SERIAL_NUMBER = 1 ; const uint32_t FT_OPEN_BY_DESCRIPTION = 2 ; const uint32_t FT_OPEN_BY_LOCATION = 4 ; const uint32_t FT_OK = 0 ; //------------------- DL (Dynamic Library) Functions ----------------------- void openLibrary() { // Open Dynamic Loadable Library with absolute path // //FunctionLib = dlopen("/mnt/home/Super4/libftd2xx.so.0.4.13", RTLD_LAZY) ; //dlError = dlerror() ; FunctionLib = dlopen ("libftd2xx.so", RTLD_LAZY) ; dlError = dlerror() ; #ifdef DEBUG printf("Open Library with absolute path return = %s\n", dlError) ; #endif if (dlError) { printf("Could not load library libftd2xx.so\n") ; exit(1) ; } } void closeLibrary() { int rc ; // Close the shared library // rc = dlclose(FunctionLib) ; dlError = dlerror() ; #ifdef DEBUG printf("Close function lib returned %s\n", dlError) ; #endif } void loadDLFunction(char* funcName) { Function = dlsym(FunctionLib, funcName) ; dlError = dlerror() ; #ifdef DEBUG printf("loaded %s, return = %s\n", funcName, dlError) ; #endif if (dlError) exit(1) ; } //-------------------------------- Relay functions ---------------------- /* List connected TCTEC Relays */ void listTCTECRelays() { uint32_t numDevices ; uint32_t temp ; uint32_t Flags ; uint32_t id ; uint32_t locID ; volatile char pcSerialNumber[255] ; uint32_t Handle ; volatile char pcDescription[255] ; uint32_t deviceType ; loadDLFunction("FT_ListDevices") ; // call the function // (*Function) ((void*) &numDevices, (void*)&temp, FT_LIST_NUMBER_ONLY) ; printf("\n\n\nFTDI Devices = %ld\n", numDevices) ; printf("--------------------------------------\n") ; // get details of connected FTDI devices // loadDLFunction("FT_CreateDeviceInfoList") ; (*Function) (&numDevices) ; printf("\n\nDevice\t\t\tSerialNumber\n") ; printf("---------------------------------------------------------\n") ; // list all the devices with the description : "TCTEC USB RELAY" // loadDLFunction("FT_GetDeviceInfoDetail") ; for(temp = 0 ; temp < numDevices; temp++) { (*Function) ((unsigned int) temp, &Flags, &deviceType, &id, &locID, pcSerialNumber, pcDescription, &Handle) ; if (strcmp(pcDescription, "TCTEC USB RELAY") == 0) { // found a relay board // printf("%s\t\t\t%s\n", pcDescription, pcSerialNumber) ; } } return; } /* Set the relay state by writing a nibble to the relay board. This also sets the drive state of the pins to "output" serialNumber: The serial number of the relay board mask: The bits to set / un-set (e.g 4 = 0100 = relay 3) on: 1 = set (on) 0 = unset (off) */ int setBits(char *serialNumber, uint8_t mask, int on) { uint32_t tempInt ; uint32_t Handle ; uint8_t bRelayStates = 0 ; uint8_t bitMode ; // open a device and set to outputs, may already be done. // loadDLFunction("FT_OpenEx") ; tempInt = (*Function) ((void*)serialNumber, FT_OPEN_BY_SERIAL_NUMBER, &Handle) ; if (tempInt != FT_OK) { printf("Device did not open, returned = %ld\n", tempInt) ; printf("serialNumber = %s\n", serialNumber) ; return(1) ; } loadDLFunction("FT_GetBitMode") ; tempInt = (*Function) (Handle, &bitMode) ; if (tempInt != FT_OK) { return(1) ; } // The bit mode only needs to be set once after first plugged in // if ((bitMode >> 4) > 0) { // bit mode has not yet been set, so set it // // set the bit mode (all inputs) // loadDLFunction("FT_SetBitMode") ; tempInt = (*Function) (Handle, 0xF0, 0x01) ; if (tempInt != FT_OK) { printf("Error setting bit mode, returned = %ld\n", tempInt) ; return(2) ; } // set all to high (off) // bRelayStates = 15 ; loadDLFunction("FT_Write") ; // write twice, as there is buffering // (*Function) (Handle, (void*) &bRelayStates, 1, &tempInt) ; (*Function) (Handle, (void*) &bRelayStates, 1, &tempInt) ; // Set up asyncronous bit bang mode all outputs // loadDLFunction("FT_SetBitMode") ; (*Function) (Handle, 0xFF, 0x01) ; } // read the current state of the bits (relays) // loadDLFunction("FT_Read") ; (*Function) (Handle, (void*)&bRelayStates, 1, (void*)&tempInt) ; // invert states, because 0 = on, 1 = off // bRelayStates = ~bRelayStates ; // if turning on, then OR with current state // if (on) { bRelayStates |= mask ; } else { bRelayStates &= ~(mask) ; // turn off } // set the relays, invert before writing out. (0 = on, 1 = off) // bRelayStates = ~bRelayStates ; #ifdef DEBUG printf("Relay state = %d\n", (int) bRelayStates) ; #endif loadDLFunction("FT_Write") ; // write twice, as there is buffering // (*Function) (Handle, (void*)&bRelayStates, 1, &tempInt) ; (*Function) (Handle, (void*)&bRelayStates, 1, &tempInt) ; loadDLFunction("FT_Close") ; tempInt = (*Function) (Handle) ; if (tempInt != FT_OK) { printf("Error. FTDI library returned %ld on FT_Close\n", tempInt) ; return(1) ; } return(0) ; } void printHelpMessage() { printf("%s\n", VERSION_STRING) ; printf("\n-------------------------------\n") ; printf("TCTEC relay command for Linux\n") ; printf("%s\n",VERSION_STRING) ; printf("www.tctec.net\n") ; printf("\n-------------------------------\n") ; printf("Commands:\n") ; printf("\n-l\t\tList all connected TCTEC relay modules\n") ; printf("\nUSAGE:\n") ; printf("lrelayset [-u,-s][SERIAL NUMBER],[MASK][ -tTIME IN MILLISECONDS]\n") ; printf("\t\t\t\t-t :optional for momentary action (1 to 10000)\n") ; printf("\t\t\t\t-u :{u}nset the relay/s\n") ; printf("\t\t\t\t-s :{s}et the relay/s\n") ; printf("\t\t\t\tMASK is a number representing bits (01 to 15)\n\n") ; printf("-s[SERIAL NUMBER],[MASK]\tSet the relays of a module (Turn ON)\n") ; printf("\t\t\t\te.g: -sFTQ57KP1,15\n") ; printf("\t\t\t\t( 15 = binary 1111. Therefore all relays on. ) ") ; printf("\n\t\t\t\te.g: -uFTQ57KP1,15\n") ; printf("\t\t\t\t( 15 = binary 1111. Therefore all relays off. ) ") ; printf("\n\n\n") ; } int main(int argc, char** argv) { char serialNum[255] =""; char* serNumEnd ; int state ; uint16_t momentaryPause = 0 ; int on ; // (1 == on, 0 == off) if (argc > 1) { openLibrary() ; // open the FTDI library // parse arguments // if (strcmp(argv[1], "-l") == 0) { listTCTECRelays() ; } else if ((strncmp(argv[1], "-s", 2) == 0) || (strncmp(argv[1], "-u", 2) == 0)) { #ifdef DEBUG printf("Setting relays\n") ; #endif state = -1 ; if (strncmp(argv[1], "-s", 2) == 0) { on = 1; } else { on = 0 ; } // find the serial number in the argument // strncpy(serialNum, (char*)&argv[1][2], 250) ; // ignore the "-s" or "-u" serNumEnd = memchr(serialNum, ',', strlen(serialNum)) ; // find the comma if (serNumEnd) { // get the state value from the string // state = atoi(serNumEnd+1) ; (*serNumEnd) = NULL ; // null terminate the serial number string } #ifdef DEBUG printf("SerialNumber = %s\n", serialNum) ; printf("State = %d\n", state) ; #endif // validate the state value // if ((state < 0) || (state > 15)) { printf("Invalid state value.\n") ; return(1) ; } // have we specified a momentary action ? // if (argc >= 3) { if (strncmp(argv[2], "-t", 2) == 0) { momentaryPause = atoi((char*)&argv[2][2]) ; // must be less than or equal to 10 seconds // if (momentaryPause > 10000) { momentaryPause = 0 ; } #ifdef DEBUG printf("Momentary Pause selected: %d milli seconds.\n", momentaryPause) ; #endif } } setBits((char*) serialNum, state, on) ; if (momentaryPause > 0) { usleep(momentaryPause*1000); // do the opposite to above, ie if relays on, then turn off // setBits(serialNum, state, ((~on) & 0x01)) ; } } else { printHelpMessage() ; } closeLibrary() ; } else // no arguments specified, so print help message { printHelpMessage() ; } exit(0) ; return(0) ; }