File kaffeine-2.0.18_support_sundtek_devices.diff of Package KaffeineLeap15p6
diff --git a/.pc/applied-patches b/.pc/applied-patches
index e69de29..a9327a6 100644
--- a/.pc/applied-patches
+++ b/.pc/applied-patches
@@ -0,0 +1 @@
+kaffeine-2.0.18_support_sundtek_devices.diff
diff --git a/src/dvb/dvbdevice_linux.cpp b/src/dvb/dvbdevice_linux.cpp
index 6843137..81fd68b 100644
--- a/src/dvb/dvbdevice_linux.cpp
+++ b/src/dvb/dvbdevice_linux.cpp
@@ -27,8 +27,18 @@ extern "C" {
#include <fcntl.h>
#include <frontend.h>
#include <poll.h>
-}
-
+ #include <sys/socket.h>
+ #include <sys/un.h>
+ #include <sys/types.h>
+ #include <sys/ioctl.h>
+ #include <sys/stat.h>
+ #include <dirent.h>
+ #include <sys/inotify.h>
+ #include <vector>
+ #include <stdlib.h>
+}
+
+#include <QDebug>
#include <QFile>
#include <QCheckBox>
#include <QMessageLogger>
@@ -47,6 +57,148 @@ extern "C" {
// krazy:excludeall=syscalls
+
+
+struct dvbdev {
+ time_t stctime;
+ char checked;
+ char adapter_name[50];
+ char node_name[75];
+ int adapternum;
+ char lnode[20];
+};
+
+class DvbDeviceMonitor : public QThread
+{
+public:
+ DvbDeviceMonitor(DvbLinuxDeviceManager *ddm)
+ {
+ this->ddm = ddm;
+ }
+ ~DvbDeviceMonitor()
+ {
+ }
+ void run() {
+ DIR *dvbdir, *adapterdirp;
+ struct dirent *dp, *dp2;
+ struct stat stbuf;
+ int adapter;
+ int rescan=0;
+ int rv;
+ int ifd;
+ int found=0;
+ char adapterdir[50];
+ char nodename[75];
+ char buffer[1024];
+ struct pollfd pfd;
+ char firstrun_complete=0;
+ std::vector<struct dvbdev*>adapterlist;
+ std::vector<struct dvbdev*>::iterator iter;
+
+ bzero(adapterdir, sizeof(adapterdir));
+ bzero(nodename, sizeof(nodename));
+ bzero(buffer, sizeof(buffer));
+
+ runstate = 1;
+
+ ifd = inotify_init();
+ inotify_add_watch(ifd, "/dev/dvb", IN_CREATE|IN_DELETE);
+ fcntl(ifd, F_SETFL, O_NONBLOCK);
+ pfd.fd = ifd;
+ pfd.events = POLLIN;
+
+ while(runstate) {
+ if (firstrun_complete) {
+ rv = poll(&pfd, 1, 100);
+ switch (rv) {
+ case -1:
+ break;
+ case 0:
+ continue;
+ default:
+ usleep(100000); /* give it some time to settle down */
+ while(read(ifd, buffer, 1024)>0);
+ break;
+ }
+ } else {
+ firstrun_complete=1;
+ }
+
+ dvbdir = opendir("/dev/dvb");
+ for (iter=adapterlist.begin();iter!=adapterlist.end();iter++) {
+ (*iter)->checked=0;
+ }
+ if (dvbdir) {
+ while((dp=readdir(dvbdir))!= 0) {
+ if (strcmp(dp->d_name, ".") == 0 ||
+ strcmp(dp->d_name, "..") == 0)
+ continue;
+ adapter = strtol(&dp->d_name[7], NULL, 10);
+ snprintf(adapterdir, 49, "/dev/dvb/%s", dp->d_name);
+ adapterdirp = opendir(adapterdir);
+ if (adapterdirp) {
+ while((dp2=readdir(adapterdirp))!=0) {
+ found=0;
+ if (strcmp(dp2->d_name, ".")==0 ||
+ strcmp(dp2->d_name, "..")==0)
+ continue;
+ snprintf(nodename, 74, "/dev/dvb/%s/%s", dp->d_name, dp2->d_name);
+ rv = stat(nodename, &stbuf);
+ for (iter=adapterlist.begin();iter!=adapterlist.end();iter++) {
+ if (strcmp((*iter)->node_name, nodename)==0 && (*iter)->stctime == stbuf.st_ctime) {
+ (*iter)->checked=1;
+ found=1;
+ break;
+ }
+ }
+ if (found == 0) {
+ struct dvbdev *dvbdev = (struct dvbdev*)calloc(1, sizeof(struct dvbdev));
+ dvbdev->checked=1;
+ dvbdev->stctime = stbuf.st_ctime;
+ strcpy(dvbdev->adapter_name, dp->d_name);
+ strcpy(dvbdev->node_name, nodename);
+ dvbdev->adapternum = adapter;
+ strcpy(dvbdev->lnode, dp2->d_name);
+ adapterlist.push_back(dvbdev);
+ ddm->componentAdded(dp2->d_name, adapter, 0);
+ }
+
+ }
+ closedir(adapterdirp);
+ }
+ }
+ closedir(dvbdir);
+ }
+ do {
+ rescan=0;
+ for (iter=adapterlist.begin();iter!=adapterlist.end();iter++) {
+ if ((*iter)->checked==0) {
+ ddm->componentRemoved((*iter)->lnode, (*iter)->adapternum, 0);
+ free(*iter);
+ adapterlist.erase(iter);
+ rescan=1;
+ break;
+ }
+ }
+ } while (rescan!=0);
+ }
+ }
+ void stop() {
+ runstate = 0;
+ wait();
+ }
+private:
+ int runstate;
+ DvbLinuxDeviceManager *ddm;
+};
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun)
+#define MACHADDRESS "/tmp/.mediasocket"
+#else
+#define ADDRESS "/de/sundtek/mediasocket" /* addr to connect */
+#endif
+
+
DvbLinuxDevice::DvbLinuxDevice(QObject *parent) : QThread(parent), ready(false), frontend(NULL),
enabled(false), dvrFd(-1), dvrBuffer(NULL, 0), cam(parent)
{
@@ -95,10 +247,25 @@ bool DvbLinuxDevice::isReady() const
return ready;
}
+extern "C" int dvb_fe_open_fname(struct dvb_v5_fe_parms *, char *fname, int flags);
+
void DvbLinuxDevice::startDevice(const QString &deviceId_)
{
Q_ASSERT(!ready);
- struct dvb_v5_fe_parms *parms = dvb_fe_open2(adapter, index, verbose, 0, dvbv5_log);
+ struct dvb_v5_fe_parms *parms;
+ if (adapter == -1) {
+ int rv;
+ parms = dvb_fe_dummy(); //(struct dvb_v5_fe_parms*)calloc(1, sizeof(struct dvb_v5_fe_parms));
+ rv = dvb_fe_open_fname(parms, strdup((char*)frontendPath.toStdString().c_str()), O_RDWR);
+ if (rv) {
+ free(parms);
+ qCWarning(logDev, "Cannot open frontend %s", qPrintable(frontendPath));
+ return;
+ }
+ } else {
+ parms = dvb_fe_open2(adapter, index, verbose, 0, dvbv5_log);
+ }
+
if (!parms) {
qCWarning(logDev, "Cannot open frontend %s", qPrintable(frontendPath));
@@ -267,7 +434,18 @@ void DvbLinuxDevice::setDeviceEnabled(bool enabled_)
bool DvbLinuxDevice::acquire()
{
Q_ASSERT(enabled && (!dvbv5_parms) && (dvrFd < 0));
- dvbv5_parms = dvb_fe_open2(adapter, index, verbose, 0, dvbv5_log);
+ if (adapter == -1) {
+ int rv;
+ dvbv5_parms = dvb_fe_dummy();
+ rv = dvb_fe_open_fname(dvbv5_parms, strdup((char*)frontendPath.toStdString().c_str()), O_RDWR);
+ if (rv) {
+ free (dvbv5_parms);
+ qCWarning(logDev, "Cannot open frontend %s", qPrintable(frontendPath));
+ return false;
+ }
+ } else {
+ dvbv5_parms = dvb_fe_open2(adapter, index, verbose, 0, dvbv5_log);
+ }
if (!dvbv5_parms) {
qCWarning(logDev, "Cannot open frontend %s", qPrintable(frontendPath));
@@ -1617,13 +1795,74 @@ void DvbLinuxDevice::run()
DvbLinuxDeviceManager::DvbLinuxDeviceManager(QObject *parent) : QObject(parent)
{
+ int fd;
+ int len;
+ int ret;
+ struct sockaddr_un saun;
QObject *notifier = Solid::DeviceNotifier::instance();
connect(notifier, SIGNAL(deviceAdded(QString)), this, SLOT(componentAdded(QString)));
connect(notifier, SIGNAL(deviceRemoved(QString)), this, SLOT(componentRemoved(QString)));
+ memset(&saun, 0x0, sizeof(struct sockaddr_un));
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd==-1) {
+ monitor = NULL;
+ return;
+ }
+ saun.sun_family = AF_UNIX;
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun)
+ strcpy(saun.sun_path, MACHADDRESS);
+ len = sizeof(saun.sun_family) + strlen(saun.sun_path)+1;
+#else
+ strcpy(&saun.sun_path[1], ADDRESS);
+ len = sizeof(saun.sun_family) + strlen(&saun.sun_path[1])+1;
+#endif
+ if ((ret=::connect(fd, (struct sockaddr*)&saun, len)) < 0) {
+ close(fd);
+ monitor = NULL;
+ return;
+ }
+ close(fd);
+ monitor = new DvbDeviceMonitor(this);
+ monitor->start();
}
DvbLinuxDeviceManager::~DvbLinuxDeviceManager()
{
+ if (monitor)
+ monitor->stop();
+}
+
+
+void DvbLinuxDeviceManager::componentAdded(QString node, int adapter, int index) {
+ qDebug() << "component added" << node << adapter << index;
+ int deviceIndex = (adapter << 16) | index;
+ DvbLinuxDevice *device = devices.value(deviceIndex, NULL);
+ if (device == NULL) {
+ device = new DvbLinuxDevice(this);
+ devices.insert(deviceIndex, device);
+ }
+
+ if (node == "frontend0") {
+ device->frontendPath=QString("/dev/dvb/adapter%1/%2").arg(QString::number(adapter)).arg(node);
+ qDebug() << "found" << device->frontendPath;
+ } else if (node == "dvr0") {
+ device->dvrPath=QString("/dev/dvb/adapter%1/%2").arg(QString::number(adapter)).arg(node);
+ } else if (node == "demux0") {
+ device->demuxPath=QString("/dev/dvb/adapter%1/%2").arg(QString::number(adapter)).arg(node);
+ } else {
+ return;
+ }
+
+ if (!device->demuxPath.isEmpty() && !device->dvrPath.isEmpty() &&
+ !device->frontendPath.isEmpty()) {
+ device->adapter = -1;
+ device->index = index;
+ device->startDevice("");
+
+ if (device->isReady()) {
+ emit deviceAdded(device);
+ }
+ }
}
void DvbLinuxDeviceManager::doColdPlug()