diff options
Diffstat (limited to 'tools/HardwareConfigure/HardwareConfigure.cpp')
-rw-r--r-- | tools/HardwareConfigure/HardwareConfigure.cpp | 424 |
1 files changed, 424 insertions, 0 deletions
diff --git a/tools/HardwareConfigure/HardwareConfigure.cpp b/tools/HardwareConfigure/HardwareConfigure.cpp new file mode 100644 index 0000000000..85b127abda --- /dev/null +++ b/tools/HardwareConfigure/HardwareConfigure.cpp @@ -0,0 +1,424 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "HardwareConfigure.h" +#include <libhal-storage.h> +#include <iostream> +#include <fstream> +#include <string.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdlib.h> + +//#define HAL_HANDLEMOUNT + +bool CHalManager::NewMessage; +DBusError CHalManager::m_Error; + +/* A Removed device, It isn't possible to make a LibHalVolume from a removed device therefor + we catch the UUID from the udi on the removal */ +void CHalManager::DeviceRemoved(LibHalContext *ctx, const char *udi) +{ + NewMessage = true; + printf("HAL: Device (%s) Removed\n", udi); +// g_HalManager.RemoveDevice(udi); +} + +void CHalManager::DeviceNewCapability(LibHalContext *ctx, const char *udi, const char *capability) +{ + NewMessage = true; + printf("HAL: Device (%s) gained capability %s\n", udi, capability); + g_HalManager.ParseDevice(udi); +} + +void CHalManager::DeviceLostCapability(LibHalContext *ctx, const char *udi, const char *capability) +{ + NewMessage = true; + printf("HAL: Device (%s) lost capability %s\n", udi, capability); + g_HalManager.ParseDevice(udi); +} + +/* HAL Property modified callback. If a device is mounted. This is called. */ +void CHalManager::DevicePropertyModified(LibHalContext *ctx, const char *udi, const char *key, dbus_bool_t is_removed, dbus_bool_t is_added) +{ + NewMessage = true; + printf("HAL: Device (%s) Property %s modified\n", udi, key); + g_HalManager.ParseDevice(udi); +} + +void CHalManager::DeviceCondition(LibHalContext *ctx, const char *udi, const char *condition_name, const char *condition_details) +{ + printf("HAL: Device (%s) Condition %s | %s\n", udi, condition_name, condition_details); + NewMessage = true; + g_HalManager.ParseDevice(udi); +} + +/* HAL Device added. This is before mount. And here is the place to mount the volume in the future */ +void CHalManager::DeviceAdded(LibHalContext *ctx, const char *udi) +{ + NewMessage = true; + printf("HAL: Device (%s) Added\n", udi); + g_HalManager.ParseDevice(udi); +} + +CHalManager g_HalManager; + +/* Iterate through all devices currently on the computer. Needed mostly at startup */ +void CHalManager::GenerateGDL() +{ + if (m_Context == NULL) + return; + + char **GDL; + int i = 0; + printf("HAL: Generating global device list\n"); + GDL = libhal_get_all_devices(g_HalManager.m_Context, &i, &m_Error); + + if (!ReadAvailableRemotes()) + return; + + for (i = 0; GDL[i]; i++) + { + if (ParseDevice(GDL[i])) + break; + } + + printf("HAL: Generated global device list, found %i\n", i); +} + +CHalManager::CHalManager() +{ +} + +// Shutdown the connection and free the context +CHalManager::~CHalManager() +{ + if (m_Context != NULL) + libhal_ctx_shutdown(m_Context, NULL); + if (m_Context != NULL) + libhal_ctx_free(m_Context); + + if (m_DBusSystemConnection != NULL) + { + dbus_connection_unref(m_DBusSystemConnection); + m_DBusSystemConnection = NULL; + } + dbus_error_free(&m_Error); // Needed? +} + +// Initialize +void CHalManager::Initialize(const char *LircConfPath) +{ + printf("HAL: Starting initializing\n"); + strcpy(m_LircConfPath, LircConfPath); + + g_HalManager.m_Context = g_HalManager.InitializeHal(); + if (g_HalManager.m_Context == NULL) + { + printf("HAL: no Hal context\n"); + return; + } + + GenerateGDL(); + + printf("HAL: Sucessfully initialized\n"); +} + +// Initialize basic DBus connection +bool CHalManager::InitializeDBus() +{ + if (m_DBusSystemConnection != NULL) + return true; + + dbus_error_init (&m_Error); + if (m_DBusSystemConnection == NULL && !(m_DBusSystemConnection = dbus_bus_get (DBUS_BUS_SYSTEM, &m_Error))) + { + printf("DBus: Could not get system bus: %s\n", m_Error.message); + dbus_error_free (&m_Error); + } + + if (m_DBusSystemConnection != NULL) + return true; + else + return false; +} + +// Initialize basic HAL connection +LibHalContext *CHalManager::InitializeHal() +{ + LibHalContext *ctx; + char **devices; + int nr; + + if (!InitializeDBus()) + return NULL; + + if (!(ctx = libhal_ctx_new())) + { + printf("HAL: failed to create a HAL context!\n"); + return NULL; + } + + if (!libhal_ctx_set_dbus_connection(ctx, m_DBusSystemConnection)) + printf("HAL: Failed to connect with dbus\n"); + + libhal_ctx_set_device_added(ctx, DeviceAdded); + libhal_ctx_set_device_removed(ctx, DeviceRemoved); + libhal_ctx_set_device_new_capability(ctx, DeviceNewCapability); + libhal_ctx_set_device_lost_capability(ctx, DeviceLostCapability); + libhal_ctx_set_device_property_modified(ctx, DevicePropertyModified); + libhal_ctx_set_device_condition(ctx, DeviceCondition); + + if (!libhal_device_property_watch_all(ctx, &m_Error)) + { + printf("HAL: Failed to set property watch %s\n", m_Error.message); + dbus_error_free(&m_Error); + libhal_ctx_free(ctx); + return NULL; + } + + if (!libhal_ctx_init(ctx, &m_Error)) + { + printf("HAL: Failed to initialize hal context: %s\n", m_Error.message); + dbus_error_free(&m_Error); + libhal_ctx_free(ctx); + return NULL; + } + + /* + * Do something to ping the HAL daemon - the above functions will + * succeed even if hald is not running, so long as DBUS is. But we + * want to exit silently if hald is not running, to behave on + * pre-2.6 systems. + */ + if (!(devices = libhal_get_all_devices(ctx, &nr, &m_Error))) + { + printf("HAL: seems that Hal daemon is not running: %s\n", m_Error.message); + dbus_error_free(&m_Error); + + libhal_ctx_shutdown(ctx, NULL); + libhal_ctx_free(ctx); + return NULL; + } + + libhal_free_string_array(devices); + + return ctx; +} + +// Called from ProcessSlow to trigger the callbacks from DBus +bool CHalManager::Update() +{ + if (m_Context == NULL) + return false; + + if (!dbus_connection_read_write_dispatch(m_DBusSystemConnection, 0)) // We choose 0 that means we won't wait for a message + { + printf("DBus: System - read/write dispatch\n"); + return false; + } + if (NewMessage) + { + NewMessage = false; + return true; + } + else + return false; +} + +/* Parse newly found device and add it to our remembered devices */ +bool CHalManager::ParseDevice(const char *udi) +{ + int VendorID, ProductID; + + VendorID = libhal_device_get_property_int(m_Context, udi, "usb.vendor_id", NULL); + ProductID = libhal_device_get_property_int(m_Context, udi, "usb.product_id", NULL); + + const char *name = IsAllowedRemote(VendorID, ProductID); + + if (name != NULL) + { + printf("HAL: Found %s - %s\n", name, udi); + if (MoveConfigs(name)) + { + printf("HAL: Sucessfully created config for %s\n", name); + return true; + + RunCommand(name); + } + else + printf("HAL: Failed to create config for %s\n", name); + } + + return false; +} + +void Tokenize(const string& path, vector<string>& tokens, const string& delimiters) +{ + // Tokenize ripped from http://www.linuxselfhelp.com/HOWTO/C++Programming-HOWTO-7.html + // Skip delimiters at beginning. + string::size_type lastPos = path.find_first_not_of(delimiters, 0); + // Find first "non-delimiter". + string::size_type pos = path.find_first_of(delimiters, lastPos); + + while (string::npos != pos || string::npos != lastPos) + { + // Found a token, add it to the vector. + tokens.push_back(path.substr(lastPos, pos - lastPos)); + // Skip delimiters. Note the "not_of" + lastPos = path.find_first_not_of(delimiters, pos); + // Find next "non-delimiter" + pos = path.find_first_of(delimiters, lastPos); + } +} + +bool CHalManager::ReadAvailableRemotes() +{ + ifstream inputfile("AvailableRemotes"); + string line; + + m_AllowedRemotes.clear(); + + if (inputfile.is_open()) + { + while (!inputfile.eof()) + { + getline(inputfile, line); + if (line.size() > 0) + { + vector<string> tokens; + Tokenize(line, tokens, " "); + + if (tokens[1].size() > 0 && tokens[0].size() > 0) + { + CHalDevice dev(atoi(tokens[1].c_str()), atoi(tokens[2].c_str()), tokens[0].c_str()); + printf("AvailableRemote: (%s) (%i) (%i)\n", dev.FriendlyName, dev.VendorID, dev.ProductID); + m_AllowedRemotes.push_back(dev); + } + } + } + inputfile.close(); + + return true; + } + return false; +} + +const char *CHalManager::IsAllowedRemote(int VendorID, int ProductID) +{ + for (unsigned int i = 0; i < m_AllowedRemotes.size(); i++) + { + if (VendorID == m_AllowedRemotes[i].VendorID && ProductID == m_AllowedRemotes[i].ProductID) + return m_AllowedRemotes[i].FriendlyName; + } + return NULL; +} + +void CHalManager::RunCommand(const char *name) +{ + char script[1024]; + sprintf(script, "%s.sh", name); + if (Exists(script)) + { + popen(script, "r"); + } +} + +bool CHalManager::MoveConfigs(const char *name) +{ + char lircd[1024], hardware[1024], lircdout[1024], hardwareout[1024]; + + sprintf(lircd, "%s.lircd.conf", name); + sprintf(lircdout, "%s/lircd.conf", m_LircConfPath); + sprintf(hardware, "%s.hardware.conf", name); + sprintf(hardwareout, "%s/hardware.conf", m_LircConfPath); + + bool temp = true; + if (!Exists(lircd)) + { + temp = false; + printf("%s didn't exist\n", lircd); + } + if (!Exists(hardware)) + { + temp = false; + printf("%s didn't exist\n", hardware); + } + if (temp) + { + bool temp2 = true; + printf("Copying %s -> %s\n", lircd, lircdout); + if (!MoveConfig(lircd, lircdout)) + { + printf("Failed to move %s -> %s\n", lircd, lircdout); + temp2 = false; + } + printf("Copying %s -> %s\n", hardware, hardwareout); + if (!MoveConfig(hardware, hardwareout)) + { + printf("Failed to move %s -> %s\n", hardware, hardwareout); + temp2 = false; + } + return temp2; + } + else + return false; +} + +bool CHalManager::Exists(const char *path) +{ + struct stat stFileInfo; + + if (stat(path, &stFileInfo) == 0) + return true; + else + return false; +} + +bool CHalManager::MoveConfig(const char *InputConfig, const char *OutputConfig) +{ + string line; + + ifstream inputfile(InputConfig); + ofstream outputfile(OutputConfig, ios_base::out); + + if (inputfile.is_open() && outputfile.is_open()) + { + while (!inputfile.eof()) + { + getline(inputfile, line); + outputfile << line <<"\n"; + } + inputfile.close(); + outputfile.close(); + return true; + } + else + return false; +} + +int main(int argc, char* argv[]) +{ + if (argc == 2) + g_HalManager.Initialize(argv[1]); + else + printf("Usage: %s PathToLircConf\n", argv[0]); +} |