From 6fb28a2e29faf239b1b14fcac981d560a7550e65 Mon Sep 17 00:00:00 2001 From: Lars Hanisch Date: Wed, 2 Feb 2011 21:44:20 +0100 Subject: add generic udev-filter Other plugins can add a filter for different subsystems and devnodes. example: AddUdevMonitor video4linux /dev/video If udev signals an "add"-event whose devnode starts with "/dev/video" the whole devnode is queued for attaching. --- dynamite.c | 32 ++++++++++++++++++++++++++++++++ monitor.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ monitor.h | 16 +++++++++++++++- udev.c | 7 +++++++ udev.h | 1 + 5 files changed, 107 insertions(+), 1 deletion(-) diff --git a/dynamite.c b/dynamite.c index 38eb69f..52b924a 100644 --- a/dynamite.c +++ b/dynamite.c @@ -219,6 +219,13 @@ bool cPluginDynamite::Service(const char *Id, void *Data) } return true; } + if (strcmp(Id, "dynamite-AddUdevMonitor-v0.1") == 0) { + if (Data != NULL) { + int replyCode; + SVDRPCommand("AddUdevMonitor", (const char*)Data, replyCode); + } + return true; + } return false; } @@ -265,6 +272,11 @@ const char **cPluginDynamite::SVDRPHelpPages(void) " Sets the \"GetTSPacket\"-watchdog timeout for all attached devices\n" " and all devices that will be attached.\n" " alternate command: SetDefaultGetTSTimeout", + "ADUM subsystem begin-of-devnode\n" + " Adds a filter to the udev-monitor.\n" + " If an event occurs whose devnode starts with the supplied parameter\n" + " this devnode will be queued for attaching.\n" + " alternate command: AddUdevMonitor", NULL }; return HelpPages; @@ -335,6 +347,26 @@ cString cPluginDynamite::SVDRPCommand(const char *Command, const char *Option, i return cString::sprintf("set default GetTS-Timeout on all devices to %d seconds", seconds); } } + + if ((strcasecmp(Command, "AUDM") == 0) || (strcasecmp(Command, "AddUdevMonitor") == 0)) { + int maxlen = strlen(Option); + if (maxlen > 0) { + char *subsystem = new char[maxlen + 1]; + char *devnode = new char[maxlen + 1]; + subsystem[0] = '\0'; + devnode[0] = '\0'; + cString msg; + if ((sscanf(Option, "%s %s", subsystem, devnode) == 2) && cUdevPatternFilter::AddFilter(subsystem, devnode)) + msg = cString::sprintf("add udev-filter for %s %s", subsystem, devnode); + else { + ReplyCode = 550; + msg = cString::sprintf("can't add udev-filter for %s %s", subsystem, devnode); + } + delete [] subsystem; + delete [] devnode; + return msg; + } + } return NULL; } diff --git a/monitor.c b/monitor.c index ff9392c..e603c30 100644 --- a/monitor.c +++ b/monitor.c @@ -218,3 +218,55 @@ void cUdevDvbFilter::Process(cUdevDevice &Device) cDynamicDeviceProbe::QueueDynamicDeviceCommand(ddpcAttach, devname); } } + +// --- cUdevPatternFilter ---------------------------------------------------- + +cMutex cUdevPatternFilter::filtersMutex; +cList cUdevPatternFilter::filters; + +bool cUdevPatternFilter::AddFilter(const char *Subsystem, const char *Pattern) +{ + if (Pattern == NULL) + return false; + cMutexLock lock(&filtersMutex); + cUdevPatternFilter *f = filters.First(); + while (f) { + if (f->monitor && (strcmp(*f->pattern, Pattern) == 0)) { + if ((Subsystem == NULL) && (*f->monitor->GetSubsystem() == NULL)) + return true; + if ((Subsystem != NULL) + && (*f->monitor->GetSubsystem() != NULL) + && (strcmp(*f->monitor->GetSubsystem(), Subsystem) == 0)) + return true; + } + f = filters.Next(f); + } + return cUdevMonitor::AddFilter(Subsystem, new cUdevPatternFilter(Pattern)); +} + +cUdevPatternFilter::cUdevPatternFilter(const char *Pattern) +:pattern(Pattern) +{ + cMutexLock lock(&filtersMutex); + filters.Add(this); +} + +cUdevPatternFilter::~cUdevPatternFilter(void) +{ + cMutexLock lock(&filtersMutex); + filters.Del(this, false); +} + +void cUdevPatternFilter::Process(cUdevDevice &Device) +{ + const char *action = Device.GetAction(); + if (action && (strcmp(action, "add") == 0)) { + const char *devname = Device.GetDevnode(); + if (devname != NULL) { + int dLen = strlen(devname); + int pLen = strlen(*pattern); + if ((pLen <= dLen) && (strncmp(devname, *pattern, pLen) == 0)) + cDynamicDeviceProbe::QueueDynamicDeviceCommand(ddpcAttach, devname); + } + } +} diff --git a/monitor.h b/monitor.h index 659e504..79634c0 100644 --- a/monitor.h +++ b/monitor.h @@ -54,5 +54,19 @@ class cUdevDvbFilter : public cUdevFilter { protected: virtual void Process(cUdevDevice &Device); }; - + +class cUdevPatternFilter : public cUdevFilter { +public: + static bool AddFilter(const char *Subsystem, const char *Pattern); +protected: + static cMutex filtersMutex; + static cList filters; + + virtual ~cUdevPatternFilter(void); + virtual void Process(cUdevDevice &Device); +private: + cUdevPatternFilter(const char *Pattern); + cString pattern; + }; + #endif // __DYNAMITEMONITOR_H diff --git a/udev.c b/udev.c index 77cc744..f37fc77 100644 --- a/udev.c +++ b/udev.c @@ -67,6 +67,13 @@ cUdevListEntry *cUdevDevice::GetDevlinksList(void) const return new cUdevListEntry(listEntry); } +const char *cUdevDevice::GetDevnode(void) const +{ + if (device == NULL) + return false; + return udev_device_get_devnode(device); +} + cUdevDevice *cUdevDevice::GetParent(void) const { if (device == NULL) diff --git a/udev.h b/udev.h index e72fe19..af079ab 100644 --- a/udev.h +++ b/udev.h @@ -25,6 +25,7 @@ public: const char *GetAction(void) const; cUdevListEntry *GetDevlinksList(void) const; + const char *GetDevnode(void) const; cUdevDevice *GetParent(void) const; const char *GetPropertyValue(const char *Key) const; const char *GetSyspath(void) const; -- cgit v1.2.3