summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HISTORY4
-rw-r--r--dynamicdevice.c20
-rw-r--r--dynamicdevice.h1
-rw-r--r--dynamite.c2
-rw-r--r--monitor.c88
-rw-r--r--monitor.h22
-rw-r--r--udev.c21
-rw-r--r--udev.h3
8 files changed, 159 insertions, 2 deletions
diff --git a/HISTORY b/HISTORY
index 703d524..6e0d287 100644
--- a/HISTORY
+++ b/HISTORY
@@ -192,3 +192,7 @@ VDR Plugin 'dynamite' Revision History
2011-09-21: Version 0.0.8a
- add SVDRP/Service commands SetIdleTimeout and SetIdleWakeup to modify the values on the fly
+
+2011-10-26: Version 0.0.8b
+
+- add udev monitor for remove events of usb hardware so devices can be detached on unplugging
diff --git a/dynamicdevice.c b/dynamicdevice.c
index a5817c7..267038a 100644
--- a/dynamicdevice.c
+++ b/dynamicdevice.c
@@ -1,5 +1,5 @@
#include "dynamicdevice.h"
-#include "udev.h"
+#include "monitor.h"
#include <glob.h>
#include <vdr/skins.h>
#include <vdr/transfer.h>
@@ -434,6 +434,7 @@ bool cDynamicDevice::IsAttached(const char *DevPath)
cDynamicDevice::cDynamicDevice()
:index(-1)
,devpath(NULL)
+,udevRemoveSyspath(NULL)
,getTSTimeoutHandlerArg(NULL)
,isDetachable(true)
,getTSTimeout(defaultGetTSTimeout)
@@ -476,6 +477,18 @@ void cDynamicDevice::ReadUdevProperties(void)
if (timeoutHandlerArg)
InternSetGetTSTimeoutHandlerArg(timeoutHandlerArg);
+ cUdevDevice *p = dev->GetParent();
+ if (p) {
+ const char *subsystem = p->GetSubsystem();
+ const char *syspath = p->GetSyspath();
+ if (subsystem && syspath && (strcmp(subsystem, "usb") == 0)) {
+ cUdevUsbRemoveFilter::AddItem(syspath, **devpath);
+ if (udevRemoveSyspath)
+ delete udevRemoveSyspath;
+ udevRemoveSyspath = new cString(syspath);
+ }
+ }
+
delete dev;
}
}
@@ -518,6 +531,11 @@ void cDynamicDevice::DeleteSubDevice()
if (devpath)
cPluginManager::CallAllServices("dynamite-event-DeviceDetached-v0.1", (void*)**devpath);
}
+ if (udevRemoveSyspath) {
+ cUdevUsbRemoveFilter::RemoveItem(**udevRemoveSyspath, GetDevPath());
+ delete udevRemoveSyspath;
+ udevRemoveSyspath = NULL;
+ }
if (devpath) {
delete devpath;
devpath = NULL;
diff --git a/dynamicdevice.h b/dynamicdevice.h
index 152a7ad..500c40b 100644
--- a/dynamicdevice.h
+++ b/dynamicdevice.h
@@ -50,6 +50,7 @@ public:
private:
int index;
cString *devpath;
+ cString *udevRemoveSyspath;
cString *getTSTimeoutHandlerArg;
bool isDetachable;
time_t getTSWatchdog;
diff --git a/dynamite.c b/dynamite.c
index 0bfa0a0..914c1ea 100644
--- a/dynamite.c
+++ b/dynamite.c
@@ -10,7 +10,7 @@
#include "menu.h"
#include "monitor.h"
-static const char *VERSION = "0.0.8a";
+static const char *VERSION = "0.0.8b";
static const char *DESCRIPTION = tr("attach/detach devices on the fly");
static const char *MAINMENUENTRY = NULL;
diff --git a/monitor.c b/monitor.c
index e603c30..824d15c 100644
--- a/monitor.c
+++ b/monitor.c
@@ -49,6 +49,22 @@ bool cUdevMonitor::AddFilter(const char *Subsystem, cUdevFilter *Filter)
return true;
}
+bool cUdevMonitor::DelFilter(const char *Subsystem, cUdevFilter *Filter)
+{
+ if (Filter == NULL)
+ return false;
+ cUdevMonitor *m = Get(Subsystem);
+ if (m == NULL) {
+ delete Filter;
+ return false;
+ }
+ if (!m->DelFilter(Filter)) {
+ delete Filter;
+ return false;
+ }
+ return true;
+}
+
void cUdevMonitor::ShutdownAllMonitors(void)
{
cMutexLock lock(&mutexMonitors);
@@ -219,6 +235,78 @@ void cUdevDvbFilter::Process(cUdevDevice &Device)
}
}
+// --- cUdevUsbRemoveFilter---------------------------------------------------
+
+cUdevUsbRemoveFilter::cItem::cItem(const char *i, const char *d)
+{
+ item = new cString(i);
+ devpath = new cString(d);
+}
+
+cUdevUsbRemoveFilter::cItem::~cItem(void)
+{
+ delete item;
+ delete devpath;
+}
+
+cMutex cUdevUsbRemoveFilter::mutexFilter;
+cUdevUsbRemoveFilter *cUdevUsbRemoveFilter::filter = NULL;
+
+void cUdevUsbRemoveFilter::Process(cUdevDevice &Device)
+{
+ const char *action = Device.GetAction();
+ const char *syspath = Device.GetSyspath();
+ if (action && syspath && (strcmp(action, "remove") == 0)) {
+ isyslog("dynamite: usb remove monitor: action = %s", action);
+ isyslog("dynamite: usb remove monitor: syspath = %s", syspath);
+ cMutexLock lock(&mutexItems);
+ for (cItem *i = items.First(); i; i = items.Next(i)) {
+ if (strcmp(**(i->item), syspath) == 0) {
+ isyslog("dynamite: usb remove monitor: force detach of %s", **(i->devpath));
+ cDynamicDeviceProbe::QueueDynamicDeviceCommand(ddpcService, *cString::sprintf("dynamite-ForceDetachDevice-v0.1 %s", **(i->devpath)));
+ }
+ }
+ }
+}
+
+void cUdevUsbRemoveFilter::AddItem(const char *item, const char *devpath)
+{
+ if ((item == NULL) || (devpath == NULL))
+ return;
+ cMutexLock lock(&mutexFilter);
+ if (filter == NULL) {
+ filter = new cUdevUsbRemoveFilter();
+ if (!cUdevMonitor::AddFilter( "usb", filter)) {
+ delete filter;
+ filter = NULL;
+ return;
+ }
+ }
+ isyslog("dynamite: usb remove monitor: add syspath = %s", item);
+ cMutexLock lock2(&filter->mutexItems);
+ filter->items.Add(new cItem(item, devpath));
+}
+
+void cUdevUsbRemoveFilter::RemoveItem(const char *item, const char *devpath)
+{
+ if ((item == NULL) || (devpath == NULL))
+ return;
+ cMutexLock lock(&mutexFilter);
+ if (filter == NULL)
+ return;
+ cMutexLock lock2(&filter->mutexItems);
+ for (cItem *i = filter->items.First(); i; i = filter->items.Next(i)) {
+ if ((strcmp(**(i->item), item) == 0) && (strcmp(**(i->devpath), devpath) == 0)) {
+ filter->items.Del(i);
+ if (filter->items.Count() == 0) {
+ cUdevMonitor::DelFilter("usb", filter);
+ filter = NULL;
+ }
+ return;
+ }
+ }
+}
+
// --- cUdevPatternFilter ----------------------------------------------------
cMutex cUdevPatternFilter::filtersMutex;
diff --git a/monitor.h b/monitor.h
index 79634c0..09d01ec 100644
--- a/monitor.h
+++ b/monitor.h
@@ -27,6 +27,7 @@ protected:
public:
static cUdevMonitor *Get(const char *Subsystem);
static bool AddFilter(const char *Subsystem, cUdevFilter *Filter);
+ static bool DelFilter(const char *Subsystem, cUdevFilter *Filter);
static void ShutdownAllMonitors(void);
virtual ~cUdevMonitor(void);
@@ -55,6 +56,27 @@ protected:
virtual void Process(cUdevDevice &Device);
};
+class cUdevUsbRemoveFilter : public cUdevFilter {
+private:
+ class cItem : public cListObject {
+ public:
+ cString *item;
+ cString *devpath;
+ cItem(const char *i, const char *d);
+ virtual ~cItem(void);
+ };
+
+ static cMutex mutexFilter;
+ static cUdevUsbRemoveFilter *filter;
+ cMutex mutexItems;
+ cList<cItem> items;
+protected:
+ virtual void Process(cUdevDevice &Device);
+public:
+ static void AddItem(const char *item, const char *devpath);
+ static void RemoveItem(const char *item, const char *devpath);
+ };
+
class cUdevPatternFilter : public cUdevFilter {
public:
static bool AddFilter(const char *Subsystem, const char *Pattern);
diff --git a/udev.c b/udev.c
index cba448a..0c4567b 100644
--- a/udev.c
+++ b/udev.c
@@ -74,6 +74,13 @@ const char *cUdevDevice::GetDevnode(void) const
return udev_device_get_devnode(device);
}
+const char *cUdevDevice::GetDevpath(void) const
+{
+ if (device == NULL)
+ return false;
+ return udev_device_get_devpath(device);
+}
+
cUdevDevice *cUdevDevice::GetParent(void) const
{
if (device == NULL)
@@ -91,6 +98,20 @@ const char *cUdevDevice::GetPropertyValue(const char *Key) const
return udev_device_get_property_value(device, Key);
}
+const char *cUdevDevice::GetSubsystem(void) const
+{
+ if (device == NULL)
+ return false;
+ return udev_device_get_subsystem(device);
+}
+
+const char *cUdevDevice::GetSysname(void) const
+{
+ if (device == NULL)
+ return false;
+ return udev_device_get_sysname(device);
+}
+
const char *cUdevDevice::GetSyspath(void) const
{
if (device == NULL)
diff --git a/udev.h b/udev.h
index 2286b0f..41fba5a 100644
--- a/udev.h
+++ b/udev.h
@@ -28,8 +28,11 @@ public:
const char *GetAction(void) const;
cUdevListEntry *GetDevlinksList(void) const;
const char *GetDevnode(void) const;
+ const char *GetDevpath(void) const;
cUdevDevice *GetParent(void) const;
const char *GetPropertyValue(const char *Key) const;
+ const char *GetSubsystem(void) const;
+ const char *GetSysname(void) const;
const char *GetSyspath(void) const;
};