Rewrote the TellStick controller

This commit is contained in:
Micke Prag 2010-10-13 12:23:01 +00:00
parent 7cfc12d8fa
commit 008feec1c3
5 changed files with 128 additions and 426 deletions

View file

@ -12,7 +12,6 @@ SET( telldus-service_SRCS
Event.cpp
Settings.cpp
TelldusMain.cpp
TellStick.cpp
)
SET( telldus-service_protocol_SRCS
Protocol.h
@ -98,6 +97,7 @@ ELSE (APPLE) #### Linux ####
EventHandler_unix.cpp
main_unix.cpp
SettingsConfuse.cpp
TellStick_libftdi.cpp
)
LIST(APPEND telldus-service_LIBRARIES
${CONFUSE_LIBRARY}

View file

@ -3,6 +3,7 @@
#include "TellStick.h"
#include <map>
#include <stdio.h>
typedef std::map<int, Controller *> ControllerMap;
@ -38,27 +39,17 @@ Controller *ControllerManager::getBestControllerById(int id) {
}
void ControllerManager::loadControllers() {
while(1) {
TellStick *controller = TellStick::findFirstDevice();
if (!controller) {
break; //All TellStick loaded
}
//Make sure this isn't already loaded
bool found = false;
for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) {
TellStick *tellstick = reinterpret_cast<TellStick *>(it->second);
if (!tellstick) { //No TellStick controller
std::list<TellStickDescriptor> list = TellStick::findAll();
std::list<TellStickDescriptor>::iterator it = list.begin();
for(; it != list.end(); ++it) {
printf("Found (%i/%i): %s\n", (*it).vid, (*it).pid, (*it).serial.c_str());
TellStick *controller = new TellStick(*it);
if (!controller->isOpen()) {
delete controller;
continue;
}
if (tellstick->serial().compare(controller->serial()) == 0) { //Found a duplicate
found = true;
break;
}
}
if (found) {
break;
}
d->lastControllerId--;
d->controllers[d->lastControllerId] = controller;
}
printf("List containing %i controllers\n", (int)d->controllers.size());
}

View file

@ -1,385 +0,0 @@
//
// C++ Implementation: TellStick
//
// Description:
//
//
// Author: Micke Prag <micke.prag@telldus.se>, (C) 2009
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "TellStick.h"
#include "../client/telldus-core.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
class TellStick::TellStickDescriptor {
public:
bool found;
std::string serial;
int vid, pid;
};
class TellStick::PrivateData {
public:
bool open;
TellStickHandle ftHandle;
TellStickDescriptor descriptor;
};
TellStick::TellStick( const TellStickDescriptor &td ) {
d = new PrivateData;
d->open = false;
d->descriptor = td;
#ifdef LIBFTDI
ftdi_init(&d->ftHandle);
int ret = ftdi_usb_open_desc(&d->ftHandle, td.vid, td.pid, NULL, td.serial.c_str());
if (ret < 0) {
ftdi_deinit(&d->ftHandle);
return;
}
d->open = true;
ftdi_usb_reset( &d->ftHandle );
ftdi_disable_bitbang( &d->ftHandle );
#else
char *tempSerial = new char[td.serial.size()+1];
#ifdef _WINDOWS
strcpy_s(tempSerial, td.serial.size()+1, td.serial.c_str());
#else
strcpy(tempSerial, td.serial.c_str());
FT_SetVIDPID(td.vid, td.pid);
#endif
FT_STATUS ftStatus = FT_OpenEx(tempSerial, FT_OPEN_BY_SERIAL_NUMBER, &d->ftHandle);
delete tempSerial;
if (ftStatus == FT_OK) {
d->open = true;
FT_SetFlowControl(d->ftHandle, FT_FLOW_NONE, 0, 0);
FT_SetTimeouts(d->ftHandle,5000,0);
}
#endif
if (d->open) {
setBaud(4800);
}
}
TellStick::~TellStick() {
if (d->open) {
#ifdef LIBFTDI
ftdi_usb_close(&d->ftHandle);
ftdi_deinit(&d->ftHandle);
#else
FT_Close(d->ftHandle);
#endif
}
delete d;
}
int TellStick::vid() const {
return d->descriptor.vid;
}
int TellStick::pid() const {
return d->descriptor.pid;
}
std::string TellStick::serial() const {
return d->descriptor.serial;
}
bool TellStick::open() const {
return d->open;
}
TellStick *TellStick::findFirstDevice(int vid, int pid) {
TellStick *tellstick = 0;
if (vid == 0 && pid == 0) {
tellstick = findFirstDevice(0x1781, 0x0C30);
if (tellstick) {
return tellstick;
}
#ifdef TELLSTICK_DUO
tellstick = findFirstDevice(0x1781, 0x0C31);
#endif
return tellstick;
}
TellStickDescriptor d = findByVIDPID(vid, pid);
if (d.found) {
#ifdef TELLSTICK_DUO
if (pid == 0x0C31) {
return new TellStickDuo(d);
}
#endif
return new TellStick(d);
}
return 0;
}
TellStick *TellStick::loadBy(int vid, int pid, const std::string &serial) {
if (vid != 0x1781) {
return 0;
}
TellStick *tellstick = 0;
if (serial.length() == 0) {
tellstick = TellStick::findFirstDevice();
} else {
TellStickDescriptor d;
d.vid = vid;
d.pid = pid;
d.serial = serial;
if (pid == 0x0C30) {
tellstick = new TellStick(d);
#ifdef TELLSTICK_DUO
} else if (pid == 0x0C31) {
tellstick = new TellStickDuo(d);
#endif
}
}
if (!tellstick) {
return 0;
}
if (tellstick->open()) {
return tellstick;
}
delete tellstick;
return 0;
}
TellStick::TellStickDescriptor TellStick::findByVIDPID( int vid, int pid ) {
TellStickDescriptor retval;
retval.found = false;
retval.vid = vid;
retval.pid = pid;
#ifdef LIBFTDI
ftdi_context ftdic;
struct ftdi_device_list *devlist, *curdev;
char serialBuffer[10];
ftdi_init(&ftdic);
int ret = ftdi_usb_find_all(&ftdic, &devlist, vid, pid);
if (ret > 0) {
for (curdev = devlist; curdev != NULL; curdev = curdev->next) {
ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10);
if (ret != 0) {
continue;
}
retval.serial = serialBuffer;
break;
}
retval.found = true;
}
ftdi_list_free(&devlist);
ftdi_deinit(&ftdic);
#else
FT_HANDLE fthHandle = 0;
FT_STATUS ftStatus = FT_OK;
try{
DWORD dwNumberOfDevices = 0;
#ifndef _WINDOWS
FT_SetVIDPID(vid, pid);
#endif
ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices);
if (ftStatus == FT_OK) {
for (int i = 0; i < (int)dwNumberOfDevices; i++) {
FT_PROGRAM_DATA pData;
char ManufacturerBuf[32];
char ManufacturerIdBuf[16];
char DescriptionBuf[64];
char SerialNumberBuf[16];
pData.Signature1 = 0x00000000;
pData.Signature2 = 0xffffffff;
pData.Version = 0x00000002; // EEPROM structure with FT232R extensions
pData.Manufacturer = ManufacturerBuf;
pData.ManufacturerId = ManufacturerIdBuf;
pData.Description = DescriptionBuf;
pData.SerialNumber = SerialNumberBuf;
ftStatus = FT_Open(i, &fthHandle);
ftStatus = FT_EE_Read(fthHandle, &pData);
if(ftStatus == FT_OK){
if(pData.VendorId == vid && pData.ProductId == pid){
ftStatus = FT_Close(fthHandle);
retval.found = true;
retval.serial = pData.SerialNumber;
break;
}
}
ftStatus = FT_Close(fthHandle);
}
}
}
catch(...){
throw;
}
#endif
return retval;
}
int TellStick::firmwareVersion() {
return 1;
}
int TellStick::send(const std::string & strMessage) {
if (!d->open) {
return TELLSTICK_ERROR_NOT_FOUND;
}
bool c = true;
#ifdef LIBFTDI
unsigned char *tempMessage = new unsigned char[strMessage.size()];
memcpy(tempMessage, strMessage.c_str(), strMessage.size());
int ret;
ret = ftdi_write_data( &d->ftHandle, tempMessage, strMessage.length() ) ;
if(ret < 0) {
c = false;
} else if(ret != strMessage.length()) {
fprintf(stderr, "wierd send length? retval %i instead of %d\n",
ret, (int)strMessage.length());
}
delete[] tempMessage;
int retrycnt = 500;
unsigned char in;
while(c && --retrycnt) {
ret = ftdi_read_data( &d->ftHandle, &in, 1);
if (ret > 0) {
if (in == '\n') {
break;
}
} else if(ret == 0) { // No data available
usleep(100);
} else { //Error
c = false;
}
}
if (!retrycnt) {
c = false;
}
#else
char *tempMessage = (char *)malloc(sizeof(char) * (strMessage.size()+1));
#ifdef _WINDOWS
strcpy_s(tempMessage, strMessage.size()+1, strMessage.c_str());
#else
strcpy(tempMessage, strMessage.c_str());
#endif
ULONG bytesWritten, bytesRead;
char in;
FT_STATUS ftStatus;
ftStatus = FT_Write(d->ftHandle, tempMessage, (DWORD)strMessage.length(), &bytesWritten);
free(tempMessage);
while(c) {
ftStatus = FT_Read(d->ftHandle,&in,1,&bytesRead);
if (ftStatus == FT_OK) {
if (bytesRead == 1) {
if (in == '\n') {
break;
}
} else { //Timeout
c = false;
}
} else { //Error
c = false;
}
}
#endif
if (!c) {
return TELLSTICK_ERROR_COMMUNICATION;
}
return TELLSTICK_SUCCESS;
}
void TellStick::setBaud(int baud) {
#ifdef LIBFTDI
int ret = ftdi_set_baudrate(&d->ftHandle, baud);
if(ret != 0) {
fprintf(stderr, "set Baud failed, retval %i\n", ret);
}
#else
FT_SetBaudRate(d->ftHandle, baud);
#endif
}
TellStickHandle TellStick::handle() const {
return d->ftHandle;
}
bool TellStick::stillConnected() const {
std::string serial = this->serial();
#ifdef LIBFTDI
ftdi_context ftdic;
struct ftdi_device_list *devlist, *curdev;
char serialBuffer[10];
ftdi_init(&ftdic);
bool found = false;
int ret = ftdi_usb_find_all(&ftdic, &devlist, this->vid(), this->pid());
if (ret > 0) {
for (curdev = devlist; curdev != NULL; curdev = curdev->next) {
ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10);
if (ret != 0) {
continue;
}
if (serial.compare(serialBuffer) == 0) {
found = true;
break;
}
}
}
ftdi_list_free(&devlist);
ftdi_deinit(&ftdic);
return found;
#else
FT_STATUS ftStatus;
DWORD numDevs;
// create the device information list
ftStatus = FT_CreateDeviceInfoList(&numDevs);
if (ftStatus != FT_OK) {
return false;
}
if (numDevs <= 0) {
return false;
}
for (int i = 0; i < (int)numDevs; i++) {
FT_HANDLE ftHandleTemp;
DWORD flags;
DWORD id;
DWORD type;
DWORD locId;
char serialNumber[16];
char description[64];
// get information for device 0
ftStatus = FT_GetDeviceInfoDetail(i, &flags, &type, &id, &locId, serialNumber, description, &ftHandleTemp);
if (ftStatus != FT_OK) {
continue;
}
if (serial.compare(serialNumber) == 0) {
return true;
}
}
return false;
#endif
}

View file

@ -13,39 +13,31 @@
#define TELLSTICK_H
#include "Controller.h"
#include <list>
#include "ftd2xx.h"
#ifdef LIBFTDI
typedef ftdi_context TellStickHandle;
#else
typedef FT_HANDLE TellStickHandle;
#endif
class TellStickDescriptor {
public:
std::string serial;
int vid, pid;
};
class TellStick : public Controller {
public:
TellStick(const TellStickDescriptor &d);
virtual ~TellStick();
virtual int firmwareVersion();
bool isOpen() const;
virtual int send( const std::string &message );
int vid() const;
int pid() const;
std::string serial() const;
bool open() const;
bool stillConnected() const;
static TellStick *findFirstDevice(int vid = 0, int pid = 0);
static TellStick *loadBy(int vid, int pid, const std::string &serial);
static std::list<TellStickDescriptor> findAll();
protected:
class TellStickDescriptor;
TellStick(const TellStickDescriptor &d);
void setBaud( int baud );
TellStickHandle handle() const;
private:
static TellStickDescriptor findByVIDPID( int vid, int pid );
static std::list<TellStickDescriptor> findAllByVIDPID( int vid, int pid );
class PrivateData;
PrivateData *d;

View file

@ -0,0 +1,104 @@
//
// C++ Implementation: TellStick
//
// Description:
//
//
// Author: Micke Prag <micke.prag@telldus.se>, (C) 2009
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "TellStick.h"
#include "../client/telldus-core.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ftdi.h>
class TellStick::PrivateData {
public:
bool open;
ftdi_context ftHandle;
};
TellStick::TellStick( const TellStickDescriptor &td ) {
d = new PrivateData;
d->open = false;
ftdi_init(&d->ftHandle);
int ret = ftdi_usb_open_desc(&d->ftHandle, td.vid, td.pid, NULL, td.serial.c_str());
if (ret < 0) {
ftdi_deinit(&d->ftHandle);
return;
}
d->open = true;
ftdi_usb_reset( &d->ftHandle );
ftdi_disable_bitbang( &d->ftHandle );
if (d->open) {
// setBaud(4800);
}
}
TellStick::~TellStick() {
if (d->open) {
ftdi_usb_close(&d->ftHandle);
ftdi_deinit(&d->ftHandle);
}
delete d;
}
int TellStick::firmwareVersion() {
return 1;
}
bool TellStick::isOpen() const {
return d->open;
}
int TellStick::send( const std::string &message ) {
return TELLSTICK_SUCCESS;
}
std::list<TellStickDescriptor> TellStick::findAll() {
std::list<TellStickDescriptor> tellstick = findAllByVIDPID(0x1781, 0x0C30);
std::list<TellStickDescriptor> duo = findAllByVIDPID(0x1781, 0x0C31);
for(std::list<TellStickDescriptor>::const_iterator it = duo.begin(); it != duo.end(); ++it) {
tellstick.push_back(*it);
}
return tellstick;
}
std::list<TellStickDescriptor> TellStick::findAllByVIDPID( int vid, int pid ) {
std::list<TellStickDescriptor> retval;
ftdi_context ftdic;
struct ftdi_device_list *devlist, *curdev;
char serialBuffer[10];
ftdi_init(&ftdic);
int ret = ftdi_usb_find_all(&ftdic, &devlist, vid, pid);
if (ret > 0) {
for (curdev = devlist; curdev != NULL; curdev = curdev->next) {
ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10);
if (ret != 0) {
continue;
}
TellStickDescriptor td;
td.vid = vid;
td.pid = pid;
td.serial = serialBuffer;
retval.push_back(td);
}
}
ftdi_list_free(&devlist);
ftdi_deinit(&ftdic);
return retval;
}