telldus/telldus-core/service/ControllerManager.cpp

181 lines
4.9 KiB
C++

#include "ControllerManager.h"
#include "Controller.h"
#include "Mutex.h"
#include "TellStick.h"
#include "Log.h"
#include "../client/telldus-core.h"
#include <map>
#include <stdio.h>
typedef std::map<int, Controller *> ControllerMap;
class ControllerManager::PrivateData {
public:
int lastControllerId;
ControllerMap controllers;
Event *event;
TelldusCore::Mutex mutex;
};
ControllerManager::ControllerManager(Event *event){
d = new PrivateData;
d->lastControllerId = 0;
d->event = event;
this->loadControllers();
}
ControllerManager::~ControllerManager() {
for (ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) {
delete( it->second );
}
delete d;
}
void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted) {
if (vid == 0x0 && pid == 0x0) { //All
if (inserted) {
loadControllers();
} else {
//Disconnect all
TelldusCore::MutexLocker locker(&d->mutex);
while(d->controllers.size()) {
ControllerMap::iterator it = d->controllers.begin();
delete it->second;
d->controllers.erase(it);
}
}
return;
}
if (vid != 0x1781) {
return;
}
if (pid != 0x0C30 && pid != 0x0C31) {
return;
}
if (inserted) {
loadControllers();
} else {
//Autodetect which has been disconnected
TelldusCore::MutexLocker locker(&d->mutex);
bool again = true;
while(again) {
again = false;
for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) {
TellStick *tellstick = reinterpret_cast<TellStick*>(it->second);
if (!tellstick) {
continue;
}
if (serial.compare("") != 0) {
TellStickDescriptor tsd;
tsd.vid = vid;
tsd.pid = pid;
tsd.serial = serial;
if (!tellstick->isSameAsDescriptor(tsd)) {
continue;
}
} else if (tellstick->stillConnected()) {
continue;
}
d->controllers.erase(it);
delete tellstick;
again=true;
break;
}
}
}
}
Controller *ControllerManager::getBestControllerById(int id) {
TelldusCore::MutexLocker locker(&d->mutex);
if (!d->controllers.size()) {
return 0;
}
ControllerMap::const_iterator it = d->controllers.find(id);
if (it != d->controllers.end()) {
return it->second;
}
return d->controllers.begin()->second;
}
void ControllerManager::loadControllers() {
TelldusCore::MutexLocker locker(&d->mutex);
std::list<TellStickDescriptor> list = TellStick::findAll();
std::list<TellStickDescriptor>::iterator it = list.begin();
for(; it != list.end(); ++it) {
//Most backend only report non-opened devices.
//If they don't make sure we don't open them twice
bool found = false;
ControllerMap::const_iterator cit = d->controllers.begin();
for(; cit != d->controllers.end(); ++cit) {
TellStick *tellstick = reinterpret_cast<TellStick*>(cit->second);
if (!tellstick) {
continue;
}
if (tellstick->isSameAsDescriptor(*it)) {
found = true;
break;
}
}
if (found) {
continue;
}
int controllerId = d->lastControllerId-1;
TellStick *controller = new TellStick(controllerId, d->event, *it);
if (!controller->isOpen()) {
delete controller;
continue;
}
d->lastControllerId = controllerId;
d->controllers[d->lastControllerId] = controller;
}
}
void ControllerManager::queryControllerStatus(){
std::list<TellStick *> tellStickControllers;
{
TelldusCore::MutexLocker locker(&d->mutex);
for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) {
TellStick *tellstick = reinterpret_cast<TellStick*>(it->second);
if (tellstick) {
tellStickControllers.push_back(tellstick);
}
}
}
bool reloadControllers = false;
std::string noop = "N+";
for(std::list<TellStick *>::iterator it = tellStickControllers.begin(); it != tellStickControllers.end(); ++it) {
int success = (*it)->send(noop);
if(success == TELLSTICK_ERROR_BROKEN_PIPE){
Log::warning("TellStick query: Error in communication with TellStick, resetting USB");
resetController(*it);
}
if(success == TELLSTICK_ERROR_BROKEN_PIPE || success == TELLSTICK_ERROR_NOT_FOUND){
reloadControllers = true;
}
}
if(!tellStickControllers.size() || reloadControllers){
//no tellstick at all found, or controller was reset
Log::debug("TellStick query: Rescanning USB ports"); //only log as debug, since this will happen all the time if no TellStick is connected
loadControllers();
}
}
int ControllerManager::resetController(Controller *controller) {
TellStick *tellstick = reinterpret_cast<TellStick*>(controller);
if (!tellstick) {
return true; //not tellstick, nothing to reset at the moment, just return true
}
int success = tellstick->reset();
deviceInsertedOrRemoved(tellstick->vid(), tellstick->pid(), tellstick->serial(), false); //remove from list and delete
return success;
}