diff options
author | Lars Hanisch <dvb@flensrocker.de> | 2011-10-26 23:02:06 +0200 |
---|---|---|
committer | Lars Hanisch <dvb@flensrocker.de> | 2011-10-26 23:02:06 +0200 |
commit | 6842192298a8c1cf38db4c51d62598b704256933 (patch) | |
tree | 7181fb99a2d9b7cb7a6a457855fe6ab9c2731869 | |
parent | 6e1064dca6de162e199b4687612d3f5f72c7c0c4 (diff) | |
download | vdr-plugin-dynamite-6842192298a8c1cf38db4c51d62598b704256933.tar.gz vdr-plugin-dynamite-6842192298a8c1cf38db4c51d62598b704256933.tar.bz2 |
add udev monitor for remove events of usb hardware so devices can be detached on unplugging
-rw-r--r-- | HISTORY | 4 | ||||
-rw-r--r-- | dynamicdevice.c | 20 | ||||
-rw-r--r-- | dynamicdevice.h | 1 | ||||
-rw-r--r-- | dynamite.c | 2 | ||||
-rw-r--r-- | monitor.c | 88 | ||||
-rw-r--r-- | monitor.h | 22 | ||||
-rw-r--r-- | udev.c | 21 | ||||
-rw-r--r-- | udev.h | 3 |
8 files changed, 159 insertions, 2 deletions
@@ -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; @@ -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; @@ -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; @@ -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); @@ -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) @@ -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; }; |