663 lines
18 KiB
C
663 lines
18 KiB
C
/****************************************************************************
|
||
** rfcmd.c ***********************************************************
|
||
****************************************************************************
|
||
*
|
||
* rfcmd - utility to control NEXA and other RF remote receivers through a TellStick
|
||
* USB interface
|
||
*
|
||
* Copyright (C) 2007 Tord Andersson <tord.o.andersson@gmail.com>
|
||
*
|
||
* License: GPL v. 2
|
||
*
|
||
* Authors:
|
||
* Tord Andersson <tord.o.andersson@gmail.com>
|
||
* Micke Prag <micke.prag@telldus.se>
|
||
* Gudmund Berggren
|
||
*
|
||
* Tapani Rintala / userspace libusb / libftdi - version 02-2009
|
||
*/
|
||
|
||
/*******************************************************************************
|
||
* Modifications from rfcmd.c ver 0.2 done by Gudmund
|
||
* Added support for IKEA
|
||
* Note:
|
||
* 1. System code
|
||
* 2. Level 0 == Off (For dimmers and non dimmers)
|
||
* Level 1== 10%. (for dimmers)
|
||
* ....
|
||
* Level 9 == 90 % (for dimmers)
|
||
* Level 10 == 100 % (or ON for non dimmers)
|
||
* 3. Command line syntax:
|
||
* /usr/local/bin/rfcmd /dev/ttyUSB0 IKEA 0 1 10 1"
|
||
* Arg 1: device
|
||
* Arg 2: Protocoll
|
||
* Arg 3: System code
|
||
* Arg 4: Device code
|
||
* Arg 5: Level (0=off, 1 = 10%, 2=20%,...9=90%, 10=100%)
|
||
* Arg 6: DimStyle (0=instant change, 1=gradually change)
|
||
******************************************************************************/
|
||
|
||
/*******************************************************************************
|
||
* Modifications to rfcmd.c ver 2.1.0 done by Tord Andersson
|
||
* Introduced semaphore protection to avoid problems with simultaneous port
|
||
* access from several processes (typically cron jobs). Note! Need rt lib.
|
||
******************************************************************************/
|
||
|
||
/*******************************************************************************
|
||
* Modifications from rfcmd.c ver 2.1.0 done by Leo
|
||
* Added support for RISINGSUN
|
||
* Note:
|
||
* 1. Command line syntax:
|
||
* /usr/local/bin/rfcmd /dev/ttyUSB0 RISINGSUN 4 1 0"
|
||
* Arg 1: device
|
||
* Arg 2: protocol
|
||
* Arg 3: code
|
||
* Arg 4: device number
|
||
* Arg 5: Level (0=off, 1 = on)
|
||
******************************************************************************/
|
||
|
||
/*******************************************************************************
|
||
* Modifications from rfcmd.c ver 2.1.0 based on marvelous work by Snakehand
|
||
* See http://www.telldus.com/forum/viewtopic.php?t=97&start=63
|
||
* Added support for EVERFLOURISH
|
||
* Note:
|
||
* 1. Command line syntax:
|
||
* /usr/local/bin/rfcmd /dev/ttyUSB0 EVERFLOURISH 1 15
|
||
* Arg 1: device
|
||
* Arg 2: protocol
|
||
* Arg 3: device number (0..65535)
|
||
* Arg 4: Level (0=off, 15=on, 10=learn)
|
||
******************************************************************************/
|
||
|
||
/*******************************************************************************
|
||
* Modifications from rfcmd ver 2.1.1 done by Johan Str<74>m
|
||
* Default disabled semaphores for FreeBSD.
|
||
* Added status readback in ftdi.c, instead of wasting time in sleep.
|
||
*
|
||
* FreeBSD does not have support in the GENERIC kernel semaphore.
|
||
* To enable usage of them, you'll have have the following option in your
|
||
* kernel configuration:
|
||
*
|
||
* options P1003_1B_SEMAPHORES
|
||
*
|
||
* However, on FreeBSD only libftdi seems to be working (at least on my system),
|
||
* since the device is not identified as a ucom device. And as we're accessing it
|
||
* via libftdi, libftdi makes sure simultaneous access is impossible.
|
||
******************************************************************************/
|
||
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <fcntl.h>
|
||
#include <unistd.h>
|
||
#include <termios.h>
|
||
|
||
#ifndef NO_SEMAPHORES
|
||
#include <semaphore.h>
|
||
#endif
|
||
|
||
#define PROG_NAME "rfcmd"
|
||
#define PROG_VERSION "2.1.1"
|
||
/* #define RFCMD_DEBUG */
|
||
|
||
/* Local function declarations */
|
||
int createNexaString(const char * pHouseStr, const char * pChannelStr,
|
||
const char * pOn_offStr, char * pTxStr, int waveman);
|
||
int createSartanoString(const char * pChannelStr, const char * pOn_offStr,
|
||
char * pTxStr);
|
||
int createIkeaString(const char * pSystemStr, const char * pChannelStr,
|
||
const char * pLevelStr, const char *pDimStyle,
|
||
char * pStrReturn);
|
||
int createRisingSunString(const char * pCodeStr, const char* pUnitStr, const char * pOn_offStr,
|
||
char * pTxStr);
|
||
int createEverFlourishString(const char* pUnitStr, const char * pLevelStr,
|
||
char * pTxStr);
|
||
void printUsage(void);
|
||
void printVersion(void);
|
||
|
||
#ifdef LIBFTDI
|
||
int usbWriteFtdi(char *cmdstr);
|
||
#endif
|
||
|
||
int main( int argc, char **argv )
|
||
{
|
||
struct termios tio;
|
||
int fd = -1;
|
||
#ifndef NO_SEMAPHORES
|
||
sem_t * portMutex;
|
||
char SEM_NAME[]= "RFCMD_SEM"; /* Semaphore for multiple access ctrl */
|
||
#endif
|
||
|
||
|
||
char txStr[100];
|
||
|
||
if( (argc == 6) && (strcmp(*(argv+2), "NEXA") == 0)) {
|
||
if (createNexaString(*(argv+3), *(argv+4), *(argv+5), txStr, 0) == 0) {
|
||
printUsage();
|
||
exit(1);
|
||
}
|
||
/* else - a send cmd string was created */
|
||
} else if( (argc == 6) && (strcmp(*(argv+2), "WAVEMAN") == 0)) {
|
||
if (createNexaString(*(argv+3),*(argv+4), *(argv+5), txStr, 1) == 0) {
|
||
printUsage();
|
||
exit(1);
|
||
}
|
||
} else if( (argc == 5) && (strcmp(*(argv+2), "SARTANO") == 0)) {
|
||
if (createSartanoString(*(argv+3), *(argv+4), txStr) == 0) {
|
||
printUsage();
|
||
exit(1);
|
||
}
|
||
/* else - a send cmd string was created */
|
||
} else if ( (argc == 7) && (strcmp(*(argv+2),"IKEA")==0) ) {
|
||
// System, Channel, Level, DimStyle, TXString
|
||
if ( createIkeaString(*(argv+3), *(argv+4), *(argv+5), *(argv+6),txStr) == 0 ) {
|
||
printUsage();
|
||
exit(1);
|
||
}
|
||
/* else - a send cmd string was created */
|
||
} else if ( (argc == 6) && (strcmp(*(argv+2),"RISINGSUN")==0) ) {
|
||
// Code, Unit, Power
|
||
if ( createRisingSunString(*(argv+3), *(argv+4), *(argv+5), txStr) == 0 ) {
|
||
printUsage();
|
||
exit(1);
|
||
}
|
||
/* else - a send cmd string was created */
|
||
} else if ( (argc == 5) && (strcmp(*(argv+2),"EVERFLOURISH")==0) ) {
|
||
// Unit, Level
|
||
if ( createEverFlourishString(*(argv+3), *(argv+4), txStr) == 0 ) {
|
||
printUsage();
|
||
exit(1);
|
||
}
|
||
/* else - a send cmd string was created */
|
||
} else if ( (argc >= 2) && (strcmp(*(argv+1),"--version")==0) ) {
|
||
printVersion();
|
||
exit(1);
|
||
} else { /* protocol or parameters not recognized */
|
||
printUsage();
|
||
exit(1);
|
||
}
|
||
|
||
#ifdef RFCMD_DEBUG
|
||
printf("txStr: %s\n", txStr);
|
||
|
||
#endif
|
||
|
||
if(strlen(txStr) > 0) {
|
||
#ifndef NO_SEMAPHORES
|
||
/* create the semaphore - will reuse an existing one if it exists */
|
||
portMutex = sem_open(SEM_NAME,O_CREAT,0644,1);
|
||
if( portMutex == SEM_FAILED) {
|
||
fprintf(stderr, "%s - Error creating port semaphore\n", PROG_NAME);
|
||
perror("Semaphore open error");
|
||
sem_unlink(SEM_NAME);
|
||
exit(1);
|
||
}
|
||
|
||
/* lock semaphore to protect port from multiple access */
|
||
if(sem_wait(portMutex) != 0) {
|
||
fprintf(stderr, "%s - Error aquiring port semaphore\n", PROG_NAME);
|
||
sem_unlink(SEM_NAME);
|
||
sem_close(portMutex);
|
||
exit(1);
|
||
}
|
||
#endif
|
||
|
||
|
||
if (strcmp(*(argv+1), "LIBUSB") != 0) {
|
||
if( 0 > ( fd = open( *(argv+1), O_RDWR ) ) ) {
|
||
#ifdef __FreeBSD__
|
||
fprintf(stderr, "%s - Error opening %s; You're on a FreeBSD system, you should probably use LIBUSB.\n", PROG_NAME, *(argv+1));
|
||
#else
|
||
fprintf(stderr, "%s - Error opening %s\n", PROG_NAME, *(argv+1));
|
||
#endif
|
||
#ifndef NO_SEMAPHORES
|
||
if(sem_post(portMutex) != 0) {
|
||
fprintf(stderr, "%s - Error releasing port semaphore\n", PROG_NAME);
|
||
}
|
||
sem_unlink(SEM_NAME);
|
||
sem_close(portMutex);
|
||
#endif
|
||
exit(1);
|
||
}
|
||
|
||
/* adjust serial port parameters */
|
||
bzero(&tio, sizeof(tio)); /* clear struct for new port settings */
|
||
tio.c_cflag = B4800 | CS8 | CLOCAL | CREAD; /* CREAD not used yet */
|
||
tio.c_iflag = IGNPAR;
|
||
tio.c_oflag = 0;
|
||
tio.c_ispeed = 4800;
|
||
tio.c_ospeed = 4800;
|
||
tcflush(fd, TCIFLUSH);
|
||
tcsetattr(fd,TCSANOW,&tio);
|
||
|
||
write(fd, txStr, strlen(txStr));
|
||
|
||
sleep(1); /* one second sleep to avoid device 'choking' */
|
||
close(fd); /* Modified : Close fd to make a clean exit */
|
||
} else {
|
||
#ifdef LIBFTDI
|
||
usbWriteFtdi( txStr );
|
||
#else
|
||
fprintf(stderr, "%s - Support for libftdi is not compiled in, please recompile rfcmd with support for libftdi\n", PROG_NAME);
|
||
#endif
|
||
}
|
||
#ifndef NO_SEMAPHORES
|
||
/* Unlock semaphore */
|
||
if (sem_post(portMutex) != 0) {
|
||
fprintf(stderr, "%s - Error releasing port semaphore\n", PROG_NAME);
|
||
sem_unlink(SEM_NAME);
|
||
sem_close(portMutex);
|
||
exit(1);
|
||
} else {
|
||
sem_unlink(SEM_NAME);
|
||
sem_close(portMutex);
|
||
}
|
||
#endif
|
||
}
|
||
exit(0);
|
||
}
|
||
|
||
|
||
int createNexaString(const char * pHouseStr, const char * pChannelStr,
|
||
const char * pOn_offStr, char * pTxStr, int waveman)
|
||
{
|
||
* pTxStr = '\0'; /* Make sure tx string is empty */
|
||
int houseCode;
|
||
int channelCode;
|
||
int on_offCode;
|
||
int txCode = 0;
|
||
const int unknownCode = 0x6;
|
||
int bit;
|
||
int bitmask = 0x0001;
|
||
|
||
houseCode = (int)((* pHouseStr) - 65); /* House 'A'..'P' */
|
||
channelCode = atoi(pChannelStr) - 1; /* Channel 1..16 */
|
||
on_offCode = atoi(pOn_offStr); /* ON/OFF 0..1 */
|
||
|
||
#ifdef RFCMD_DEBUG
|
||
printf("House: %d, channel: %d, on_off: %d\n", houseCode, channelCode, on_offCode);
|
||
#endif
|
||
|
||
/* check converted parameters for validity */
|
||
if((houseCode < 0) || (houseCode > 15) || // House 'A'..'P'
|
||
(channelCode < 0) || (channelCode > 15) ||
|
||
(on_offCode < 0) || (on_offCode > 1))
|
||
{
|
||
|
||
} else {
|
||
/* b0..b11 txCode where 'X' will be represented by 1 for simplicity.
|
||
b0 will be sent first */
|
||
txCode = houseCode;
|
||
txCode |= (channelCode << 4);
|
||
if (waveman && on_offCode == 0) {
|
||
} else {
|
||
txCode |= (unknownCode << 8);
|
||
txCode |= (on_offCode << 11);
|
||
}
|
||
|
||
/* convert to send cmd string */
|
||
strcat(pTxStr,"S");
|
||
for(bit=0;bit<12;bit++)
|
||
{
|
||
if((bitmask & txCode) == 0) {
|
||
/* bit timing might need further refinement */
|
||
strcat(pTxStr," ` `"); /* 320 us high, 960 us low, 320 us high, 960 us low */
|
||
/* strcat(pTxStr,"$k$k"); *//* 360 us high, 1070 us low, 360 us high, 1070 us low */
|
||
} else { /* add 'X' (floating bit) */
|
||
strcat(pTxStr," `` "); /* 320 us high, 960 us low, 960 us high, 320 us low */
|
||
/*strcat(pTxStr,"$kk$"); *//* 360 us high, 1070 us low, 1070 us high, 360 us low */
|
||
}
|
||
bitmask = bitmask<<1;
|
||
}
|
||
/* add stop/sync bit and command termination char '+'*/
|
||
strcat(pTxStr," }+");
|
||
/* strcat(pTxStr,"$}+"); */
|
||
}
|
||
|
||
#ifdef RFCMD_DEBUG
|
||
printf("txCode: %04X\n", txCode);
|
||
#endif
|
||
|
||
return strlen(pTxStr);
|
||
}
|
||
|
||
int createSartanoString(const char * pChannelStr, const char * pOn_offStr,
|
||
char * pTxStr)
|
||
{
|
||
* pTxStr = '\0'; /* Make sure tx string is empty */
|
||
int on_offCode;
|
||
int bit;
|
||
|
||
on_offCode = atoi(pOn_offStr); /* ON/OFF 0..1 */
|
||
|
||
#ifdef RFCMD_DEBUG
|
||
printf("Channel: %s, on_off: %d\n", pChannelStr, on_offCode);
|
||
#endif
|
||
|
||
/* check converted parameters for validity */
|
||
if((strlen(pChannelStr) != 10) ||
|
||
(on_offCode < 0) || (on_offCode > 1)) {
|
||
} else {
|
||
strcat(pTxStr,"S");
|
||
for(bit=0;bit<=9;bit++)
|
||
{
|
||
if(strncmp(pChannelStr+bit, "1", 1) == 0) { //If it is a "1"
|
||
strcat(pTxStr,"$k$k");
|
||
} else {
|
||
strcat(pTxStr,"$kk$");
|
||
}
|
||
}
|
||
if (on_offCode >= 1)
|
||
strcat(pTxStr,"$k$k$kk$"); //the "turn on"-code
|
||
else
|
||
strcat(pTxStr,"$kk$$k$k"); //the "turn off"-code
|
||
|
||
/* add stop/sync bit and command termination char '+'*/
|
||
strcat(pTxStr,"$k+");
|
||
}
|
||
|
||
return strlen(pTxStr);
|
||
}
|
||
|
||
int createIkeaString( const char * pSystemStr, const char * pChannelStr, const char * pLevelStr, const char *pDimStyle, char * pStrReturn)
|
||
{
|
||
*pStrReturn = '\0'; /* Make sure tx string is empty */
|
||
|
||
const char STARTCODE[] = "STTTTTT<EFBFBD>";
|
||
const char TT[] = "TT";
|
||
const char A[] = "<EFBFBD>";
|
||
int systemCode = atoi(pSystemStr) - 1; /* System 1..16 */
|
||
int channelCode = atoi(pChannelStr); /* Channel 1..10 */
|
||
int Level = atoi(pLevelStr); /* off,10,20,..,90,on */
|
||
int DimStyle = atoi(pDimStyle);
|
||
int intCode = 0;
|
||
int checksum1 = 0;
|
||
int checksum2 = 0;
|
||
int intFade ;
|
||
int i ;
|
||
int rawChannelCode = 0;
|
||
|
||
/* check converted parameters for validity */
|
||
if ( (channelCode <= 0) || (channelCode > 10) ||
|
||
(systemCode < 0) || (systemCode > 15) ||
|
||
(Level < 0) || (Level > 10) ||
|
||
(DimStyle < 0) || (DimStyle > 1))
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
if (channelCode == 10) {
|
||
channelCode = 0;
|
||
}
|
||
rawChannelCode = (1<<(9-channelCode));
|
||
|
||
strcat(pStrReturn, STARTCODE ) ; //Startcode, always like this;
|
||
intCode = (systemCode << 10) | rawChannelCode;
|
||
|
||
for ( i = 13; i >= 0; --i) {
|
||
if ((intCode>>i) & 1) {
|
||
strcat(pStrReturn, TT );
|
||
if (i % 2 == 0) {
|
||
checksum2++;
|
||
} else {
|
||
checksum1++;
|
||
}
|
||
} else {
|
||
strcat(pStrReturn,A);
|
||
}
|
||
}
|
||
|
||
if (checksum1 %2 == 0) {
|
||
strcat(pStrReturn, TT );
|
||
} else {
|
||
strcat(pStrReturn, A) ; //1st checksum
|
||
}
|
||
|
||
if (checksum2 %2 == 0) {
|
||
strcat(pStrReturn, TT );
|
||
} else {
|
||
strcat(pStrReturn, A ) ; //2nd checksum
|
||
}
|
||
|
||
if (DimStyle == 1) {
|
||
intFade = 11 << 4; //Smooth
|
||
} else {
|
||
intFade = 1 << 4; //Instant
|
||
}
|
||
|
||
switch ( Level )
|
||
{
|
||
case 0 :
|
||
intCode = (10 | intFade) ; //Concat level and fade
|
||
break;
|
||
case 1 :
|
||
intCode = (1 | intFade) ; //Concat level and fade
|
||
break;
|
||
case 2 :
|
||
intCode = (2 | intFade) ; //Concat level and fade
|
||
break;
|
||
case 3 :
|
||
intCode = (3 | intFade) ; //Concat level and fade
|
||
break;
|
||
case 4 :
|
||
intCode = (4 | intFade) ; //Concat level and fade
|
||
break;
|
||
case 5 :
|
||
intCode = (5 | intFade) ; //Concat level and fade
|
||
break;
|
||
case 6 :
|
||
intCode = (6 | intFade) ; //Concat level and fade
|
||
break;
|
||
case 7 :
|
||
intCode = (7 | intFade) ; //Concat level and fade
|
||
break;
|
||
case 8 :
|
||
intCode = (8 | intFade) ; //Concat level and fade
|
||
break;
|
||
case 9 :
|
||
intCode = (9 | intFade) ; //Concat level and fade
|
||
break;
|
||
case 10 :
|
||
default :
|
||
intCode = (0 | intFade) ; //Concat level and fade
|
||
break;
|
||
}
|
||
|
||
checksum1 = 0;
|
||
checksum2 = 0;
|
||
|
||
for (i = 0; i < 6; ++i) {
|
||
if ((intCode>>i) & 1) {
|
||
strcat(pStrReturn, TT);
|
||
|
||
if (i % 2 == 0) {
|
||
checksum1++;
|
||
} else {
|
||
checksum2++;
|
||
}
|
||
} else {
|
||
strcat(pStrReturn, A );
|
||
}
|
||
}
|
||
|
||
if (checksum1 %2 == 0) {
|
||
strcat(pStrReturn, TT);
|
||
} else {
|
||
strcat(pStrReturn, A ) ; //2nd checksum
|
||
}
|
||
|
||
if (checksum2 %2 == 0) {
|
||
strcat(pStrReturn, TT );
|
||
} else {
|
||
strcat(pStrReturn, A ) ; //2nd checksum
|
||
}
|
||
|
||
strcat(pStrReturn, "+");
|
||
|
||
return strlen(pStrReturn);
|
||
}
|
||
|
||
int createRisingSunString(const char * pCodeStr, const char * pUnitStr, const char * pOn_offStr,
|
||
char * pTxStr)
|
||
{
|
||
* pTxStr = '\0'; /* Make sure tx string is empty */
|
||
int on_offCode;
|
||
int unit;
|
||
int code;
|
||
int i;
|
||
|
||
on_offCode = atoi(pOn_offStr); /* ON/OFF 0..1 */
|
||
code = atoi (pCodeStr);
|
||
unit = atoi (pUnitStr);
|
||
|
||
#ifdef RFCMD_DEBUG
|
||
printf("Code: %s, unit: %s, on_off: %d\n", pCodeStr, pUnitStr, on_offCode);
|
||
#endif
|
||
|
||
/* check converted parameters for validity */
|
||
if((code < 1) || (code > 4) ||
|
||
(unit < 1) || (unit > 4) ||
|
||
(on_offCode < 0) || (on_offCode > 1)) {
|
||
} else {
|
||
strcat(pTxStr,"S.e");
|
||
for (i = 1; i <= 4; ++i) {
|
||
if (i == code) {
|
||
strcat (pTxStr, ".e.e");
|
||
} else {
|
||
strcat (pTxStr, "e..e");
|
||
}
|
||
}
|
||
for (i = 1; i <= 4; ++i) {
|
||
if (i == unit) {
|
||
strcat (pTxStr, ".e.e");
|
||
} else {
|
||
strcat (pTxStr, "e..e");
|
||
}
|
||
}
|
||
|
||
if (on_offCode >= 1) {
|
||
strcat(pTxStr,"e..ee..ee..ee..e+"); //the "turn on"-code
|
||
} else {
|
||
strcat(pTxStr,"e..ee..ee..e.e.e+"); //the "turn off"-code
|
||
}
|
||
}
|
||
|
||
return strlen(pTxStr);
|
||
}
|
||
|
||
unsigned int everflourish_find_code(unsigned int x) {
|
||
unsigned int bits[16] = { 0xf ,0xa ,0x7 ,0xe,
|
||
0xf ,0xd ,0x9 ,0x1,
|
||
0x1 ,0x2 ,0x4 ,0x8,
|
||
0x3 ,0x6 ,0xc ,0xb };
|
||
unsigned int bit = 1;
|
||
unsigned int res = 0x5;
|
||
int i;
|
||
unsigned int lo,hi;
|
||
|
||
if ((x&0x3)==3) {
|
||
lo = x & 0x00ff;
|
||
hi = x & 0xff00;
|
||
lo += 4;
|
||
if (lo>0x100) lo = 0x12;
|
||
x = lo | hi;
|
||
}
|
||
|
||
for(i=0;i<16;i++) {
|
||
if (x&bit) {
|
||
res = res ^ bits[i];
|
||
}
|
||
bit = bit << 1;
|
||
}
|
||
|
||
return res;
|
||
}
|
||
|
||
|
||
int createEverFlourishString(const char * pUnitStr, const char * pLevelStr,
|
||
char * pTxStr)
|
||
{
|
||
int len = 0;
|
||
int level;
|
||
int unit;
|
||
unsigned int check;
|
||
int i;
|
||
|
||
unit = atoi(pUnitStr);
|
||
level = atoi(pLevelStr); /* ON=15, OFF=0, LEARN=10 */
|
||
check = everflourish_find_code(unit);
|
||
|
||
#ifdef RFCMD_DEBUG
|
||
printf("unit: %d, level: %d\n", unit, level);
|
||
#endif
|
||
|
||
/* check converted parameters for validity */
|
||
if((unit < 0) || (unit > 0xffff) ||
|
||
(level < 0) || (level > 15)) {
|
||
} else {
|
||
const char ssss = 85;
|
||
const char sssl = 84; // 0
|
||
const char slss = 69; // 1
|
||
|
||
const char bits[2] = {sssl,slss};
|
||
int i;
|
||
|
||
char preamble[] = {'R', 5, 'T', 114,60,1,1,105,ssss,ssss};
|
||
memcpy(pTxStr, preamble, sizeof(preamble));
|
||
len += sizeof(preamble);
|
||
|
||
for(i=15;i>=0;i--) pTxStr[len++]=bits[(unit>>i)&0x01];
|
||
for(i=3;i>=0;i--) pTxStr[len++]=bits[(check>>i)&0x01];
|
||
for(i=3;i>=0;i--) pTxStr[len++]=bits[(level>>i)&0x01];
|
||
|
||
pTxStr[len++] = ssss;
|
||
pTxStr[len++] = '+';
|
||
}
|
||
|
||
pTxStr[len] = '\0';
|
||
return strlen(pTxStr);
|
||
}
|
||
|
||
void printUsage(void)
|
||
{
|
||
printf("Usage: rfcmd DEVICE PROTOCOL [PROTOCOL_ARGUMENTS] \n");
|
||
printf("\n");
|
||
#ifdef LIBFTDI
|
||
printf("\t DEVICE: /dev/ttyUSB[0..n] | LIBUSB\n" );
|
||
#else
|
||
printf("\t DEVICE: /dev/ttyUSB[0..n]\n" );
|
||
#endif
|
||
printf("\t PROTOCOLS: NEXA, SARTANO, WAVEMAN, IKEA, RISINGSUN, EVERFLOURISH\n" );
|
||
printf("\n");
|
||
printf("\t PROTOCOL ARGUMENTS - NEXA, WAVEMAN:\n");
|
||
printf("\t\tHOUSE_CODE: A..P\n\t\tCHANNEL: 1..16\n\t\tOFF_ON: 0..1\n" );
|
||
printf("\n");
|
||
printf("\t PROTOCOL ARGUMENTS - SARTANO:\n");
|
||
printf("\t\tCHANNEL: 0000000000..1111111111\n\t\tOFF_ON: 0..1\n" );
|
||
printf("\n");
|
||
printf("\t PROTOCOL ARGUMENTS - IKEA:\n");
|
||
printf("\t\tSYSTEM: 1..16\n\t\tDEVICE: 1..10\n");
|
||
printf("\t\tDIM_LEVEL: 0..10\n\t\tDIM_STYLE: 0..1\n" );
|
||
printf("\n");
|
||
printf("\t PROTOCOL ARGUMENTS - RISINGSUN:\n");
|
||
printf("\t\tCODE: 1..4\n\t\tDEVICE: 1..4\n");
|
||
printf("\t\tOFF_ON: 0..1\n" );
|
||
printf("\n");
|
||
printf("\t PROTOCOL ARGUMENTS - EVERFLOURISH:\n");
|
||
printf("\t\tDEVICE: 0..65535\n");
|
||
printf("\t\tLEVEL: 0=off, 10=learn, 15=on\n" );
|
||
printf("\n");
|
||
printf("Report bugs to <info.tech@telldus.se>\n");
|
||
}
|
||
|
||
void printVersion(void) {
|
||
printf("%s v%s\n", PROG_NAME, PROG_VERSION);
|
||
printf("\n");
|
||
printf("Copyright (C) Tord Andersson 2007\n");
|
||
printf("\n");
|
||
printf("Written by:\n");
|
||
printf("Tord Andersson, Micke Prag, Gudmund Berggren, Tapani Rintala\n");
|
||
printf("and Johan Str<74>m\n");
|
||
}
|
||
|