qmisdnwatch - mISDN v2 GUI swissknife

http://www.misdn.org/index.php/Qmisdnwatch
needs Qt4, compiles via 'qmake && make'
This commit is contained in:
Martin Bachem 2008-10-28 23:16:19 +01:00
parent a66a3c83b0
commit 9f442954dc
11 changed files with 1348 additions and 0 deletions

View File

@ -0,0 +1,40 @@
qmisdnwatch
AUTHOR
-------
Martin Bachem
m.bachem@gmx.de
LICENSE
--------
qmisdnwatch 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 version 2
qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
REQUIREMENTS
-------------
mISDN v2
Qt4
COMPILE / RUN
---------------
qmake
make
./qmisdnwatch
DOCs
-----
http://www.misdn.org/index.php/Qmisdnwatch
<end of file>

View File

@ -0,0 +1,10 @@
TEMPLATE = app
TARGET =
DEPENDPATH += . src
INCLUDEPATH += . src
# not yet ;) LIBS += -lmisdn
# Input
HEADERS += src/mainWindow.h src/misdn.h src/extraWidgets.h src/Ql1logThread.h
SOURCES += src/main.cpp src/mainWindow.cpp src/misdn.cpp src/extraWidgets.cpp src/Ql1logThread.cpp

View File

@ -0,0 +1,92 @@
/* $Id: Ql1logThread.cpp 4 2008-10-28 00:04:24Z daxtar $
* (c) 2008 Martin Bachem, m.bachem@gmx.de
*
* This file is part of qmisdnwatch
*
* Project's Home
* http://www.misdn.org/index.php/Qmisdnwatch
*
* qmisdnwatch 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 version 2
*
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <QByteArray>
#include <sys/ioctl.h>
#include "misdn.h"
#include "Ql1logThread.h"
void Ql1logThread::run(void)
{
struct sockaddr_mISDN addr;
int log_socket;
dch_echo = misdn.openl1Log(devId, protocol, &log_socket, &addr);
qDebug("Ql1logThread::run log_socket(%i) devId(%d) proto(%d)",
log_socket, devId, protocol);
if (log_socket >= 0)
{
struct msghdr mh;
struct iovec iov[1];
struct ctstamp cts;
int ret;
int buflen = 512;
unsigned char buffer[buflen];
while (1) {
mh.msg_name = NULL;
mh.msg_namelen = 0;
mh.msg_iov = iov;
mh.msg_iovlen = 1;
mh.msg_control = &cts;
mh.msg_controllen = sizeof(cts);
mh.msg_flags = 0;
iov[0].iov_base = buffer;
iov[0].iov_len = buflen;
ret = recvmsg(log_socket, &mh, 0);
if (ret >= 0) {
if (cts.cmsg_type != MISDN_TIME_STAMP) {
cts.tv.tv_sec = 0;
cts.tv.tv_usec = 0;
}
QByteArray * data = new QByteArray((const char *)buffer, ret);
emit rcvData(devId, *data, cts.tv);
}
}
} else
qDebug("ERROR connecting log_socket");
}
void Ql1logThread::setProtocol(int p) {
protocol = p;
qDebug("Ql1logThread protocol %d (%d)", protocol, p);
}
int Ql1logThread::getProtocol(void) {
return protocol;
}
int Ql1logThread::hasEcho(void) {
return (dch_echo);
}
Ql1logThread::Ql1logThread(int id, mISDN & m) : devId(id), misdn(m) {
dch_echo = -1;
connect(this, SIGNAL(finished()), this, SLOT(finish()));
}
void Ql1logThread::finish() {
close(log_socket);
emit finished(devId);
}

View File

@ -0,0 +1,60 @@
/* $Id: Ql1logThread.h 4 2008-10-28 00:04:24Z daxtar $
* (c) 2008 Martin Bachem, m.bachem@gmx.de
*
* This file is part of qmisdnwatch
*
* Project's Home
* http://www.misdn.org/index.php/Qmisdnwatch
*
* qmisdnwatch 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 version 2
*
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _QL1LOGTHREAD_H_
#define _QL1LOGTHREAD_H_
#include <QObject>
#include <QThread>
#include <QByteArray>
#include "misdn.h"
class Ql1logThread : public QThread
{
Q_OBJECT
private:
int devId;
mISDN & misdn;
int protocol;
int log_socket;
int dch_echo;
struct sockaddr_mISDN log_addr;
public:
Ql1logThread(int id, mISDN & m);
void setProtocol(int p);
int getProtocol(void);
int hasEcho(void);
protected:
void run();
public slots:
void finish();
signals:
void finished(unsigned int id);
void rcvData(unsigned int id, QByteArray data, struct timeval);
};
#endif // _QL1LOGTHREAD_H_

View File

@ -0,0 +1,35 @@
/* $Id: extraWidgets.cpp 4 2008-10-28 00:04:24Z daxtar $
* (c) 2008 Martin Bachem, m.bachem@gmx.de
*
* This file is part of qmisdnwatch
*
* Project's Home
* http://www.misdn.org/index.php/Qmisdnwatch
*
* qmisdnwatch 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 version 2
*
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <QObject>
#include <QWidget>
#include <QPushButton>
#include "extraWidgets.h"
idButton::idButton( const QString& text, unsigned int id, QWidget* parent )
: QPushButton(text, parent), devId(id) {
connect(this, SIGNAL(clicked()), this, SLOT(click()));
}
void idButton::click() {
emit clicked(devId);
}

View File

@ -0,0 +1,41 @@
/* $Id: extraWidgets.h 4 2008-10-28 00:04:24Z daxtar $
* (c) 2008 Martin Bachem, m.bachem@gmx.de
*
* This file is part of qmisdnwatch
*
* Project's Home
* http://www.misdn.org/index.php/Qmisdnwatch
*
* qmisdnwatch 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 version 2
*
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _EXTRA_WIDGETS_H_
#define _EXTRA_WIDGETS_H_
#include <QPushButton>
/* QBushbutton sending mISDN device ID at clicked() signal */
class idButton : public QPushButton {
Q_OBJECT
public:
idButton( const QString& text, unsigned int id, QWidget* parent = NULL );
private:
unsigned int devId;
public slots:
void click();
signals:
void clicked(unsigned int id);
};
#endif // _EXTRA_WIDGETS_H_

View File

@ -0,0 +1,39 @@
/* $Id: main.cpp 4 2008-10-28 00:04:24Z daxtar $
* (c) 2008 Martin Bachem, m.bachem@gmx.de
*
* This file is part of qmisdnwatch
*
* Project's Home
* http://www.misdn.org/index.php/Qmisdnwatch
*
* qmisdnwatch 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 version 2
*
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <QApplication>
#include "mainWindow.h"
#include "misdn.h"
Q_DECLARE_METATYPE(timeval);
QDataStream &operator<<( QDataStream &out, const timeval& ) { return out; }
QDataStream &operator>>( QDataStream &in, timeval& ) { return in; }
int main(int argc, char *argv[]) {
qRegisterMetaType<timeval>("timeval");
qRegisterMetaTypeStreamOperators<timeval>("timeval");
QApplication app(argc, argv);
mainWindow* window = new mainWindow;
window->show();
return app.exec();
}

View File

@ -0,0 +1,662 @@
/* $Id: mainWindow.cpp 7 2008-10-28 22:06:36Z daxtar $
* (c) 2008 Martin Bachem, m.bachem@gmx.de
*
* This file is part of qmisdnwatch
*
* Project's Home
* http://www.misdn.org/index.php/Qmisdnwatch
*
* qmisdnwatch 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 version 2
*
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <QApplication>
#include <QVBoxLayout>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QTimer>
#include <QLabel>
#include <QInputDialog>
#include <QByteArray>
#include <QFile>
#include <QFileDialog>
#include <QDataStream>
#include <QMessageBox>
#include <QMenuBar>
#include <QMenu>
#include <mISDNuser/mISDNif.h>
#include "mainWindow.h"
struct isdnDeviceStuff * mainWindow::getStuffbyId(unsigned int id) {
int i;
for (i=0; i<devStack.count(); i++)
if (devStack[i].id == id)
return &devStack[i];
return NULL;
}
struct mISDN_devinfo * mainWindow::getDevInfoById(unsigned int id) {
int i;
for (i=0; i<deviceList.count(); i++)
if (deviceList[i].id == id)
return &deviceList[i];
return NULL;
}
int mainWindow::renameDevice(unsigned int id) {
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
if (!thisDevStuff)
return -1;
struct mISDN_devinfo * devInfo = getDevInfoById(id);
if (!devInfo)
return -1;
bool inputOk;
QString newName = QInputDialog::getText(this, tr("device Name"), "new device name:",
QLineEdit::Normal, QString(devInfo->name), &inputOk);
if (inputOk && !newName.isEmpty()) {
if (strcmp(newName.toAscii().data(), devInfo->name) != 0) {
deviceListTimer->stop();
if (!misdn.renameLayer1(id, newName.toAscii().data())) {
strncpy(devInfo->name, newName.toAscii().data(), MISDN_MAX_IDLEN);
tabsheet->setTabText(thisDevStuff->tabId, newName);
thisDevStuff->treeHead->setText(0, newName);
debugOut(thisDevStuff->log, tr("renamed device to '%1'\n")
.arg(newName));
} else {
debugOut(thisDevStuff->log, tr("ERROR: renaming to '%1' failed\n")
.arg(newName));
}
deviceListTimer->start(1000);
}
}
return 0;
}
int mainWindow::cleanL2(unsigned int id) {
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
if (!thisDevStuff)
return -1;
int ret = misdn.cleanl2(id);
if (ret >= 0)
debugOut(thisDevStuff->log, tr("cleansed Layer2\n"));
else {
debugOut(thisDevStuff->log, tr("ERROR: cleaning L2 failed: "));
if (ret == -4)
debugOut(thisDevStuff->log, tr("no L2 protocol set\n"));
else if (ret == -1)
debugOut(thisDevStuff->log, tr("ioctrl invalid argument\n"));
else
debugOut(thisDevStuff->log, QString("%1\n").arg(ret));
}
return 0;
}
int mainWindow::logFinished(unsigned int id) {
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
if (!thisDevStuff)
return -1;
debugOut(thisDevStuff->log, tr("logging stopped\n"));
if (thisDevStuff->l1log->hasEcho())
thisDevStuff->buttonLogL1->setText(tr("start D-/E-Channel logging"));
else
thisDevStuff->buttonLogL1->setText(tr("start D-Channel logging"));
return 0;
}
void mainWindow::eyeSDNappend(QByteArray & target, QByteArray & data, int offset) {
for (int i=offset; i<data.count(); i++) {
unsigned char byte = data[i];
if ((byte == 0xFF) || (byte == 0xFE)) {
target.append(0xFE);
byte -= 2;
}
target.append(byte);
}
}
void mainWindow::logRcvData(unsigned int id, QByteArray data, struct timeval tv) {
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
struct mISDN_devinfo * devInfo = getDevInfoById(id);
struct tm *mt;
unsigned char origin;
int len;
if ((!thisDevStuff) || (!devInfo))
return;
unsigned char buffer[data.count()];
for (int i=0; i<data.count(); i++)
buffer[i] = data[i];
struct mISDNhead * hh = (struct mISDNhead *)buffer;
QString timeStr("");
mt = localtime((time_t *)&tv.tv_sec);
timeStr.sprintf("%02d.%02d.%04d %02d:%02d:%02d.%06ld:\t", mt->tm_mday, mt->tm_mon + 1, mt->tm_year + 1900,
mt->tm_hour, mt->tm_min, mt->tm_sec, tv.tv_usec);
debugOut(thisDevStuff->log, timeStr);
debugOut(thisDevStuff->log, QString("prim(0x%1)\tid(%2)")
.arg(QString::number(hh->prim, 16))
.arg(QString::number(hh->id, 16)));
binaryOut(thisDevStuff->log, data, sizeof(struct mISDNhead));
// collect data as eyeSDN stream to SaveAs wireshark readable
if (thisDevStuff->l1log->hasEcho() && (hh->prim == PH_DATA_REQ))
return;
if ((hh->prim != PH_DATA_REQ) && (hh->prim != PH_DATA_IND) &&
(hh->prim != PH_DATA_E_IND))
return;
if (devInfo->protocol == ISDN_P_NT_S0 || devInfo->protocol == ISDN_P_NT_E1)
origin = hh->prim == PH_DATA_REQ ? 0 : 1;
else
origin = ((hh->prim == PH_DATA_REQ) ||
(hh->prim == PH_DATA_E_IND)) ? 1 : 0;
len = data.count() - MISDN_HEADER_LEN;
QByteArray eyeHeader;
eyeHeader.append((unsigned char)(0xff & (tv.tv_usec >> 16)));
eyeHeader.append((unsigned char)(0xff & (tv.tv_usec >> 8)));
eyeHeader.append((unsigned char)(0xff & tv.tv_usec));
eyeHeader.append((char)0);
eyeHeader.append((unsigned char)(0xff & (tv.tv_sec >> 24)));
eyeHeader.append((unsigned char)(0xff & (tv.tv_sec >> 16)));
eyeHeader.append((unsigned char)(0xff & (tv.tv_sec >> 8)));
eyeHeader.append((unsigned char)(0xff & tv.tv_sec));
eyeHeader.append((char)0);
eyeHeader.append((unsigned char) origin);
eyeHeader.append((unsigned char)(0xff & (len >> 8)));
eyeHeader.append((unsigned char)(0xff & len));
/* add Frame escaped */
thisDevStuff->eyeSDN.append(0xFF);
eyeSDNappend(thisDevStuff->eyeSDN, eyeHeader, 0);
eyeSDNappend(thisDevStuff->eyeSDN, data, sizeof(struct mISDNhead));
}
int mainWindow::switchL1Logging(unsigned int id) {
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
struct mISDN_devinfo * devInfo = getDevInfoById(id);
if ((!thisDevStuff) || (!devInfo))
return -1;
if (thisDevStuff->l1log->isRunning()) {
thisDevStuff->l1log->terminate();
thisDevStuff->l1log->wait(1000);
if (thisDevStuff->l1log->isRunning()) {
debugOut(thisDevStuff->log, tr("ERROR: stop logging failed\n"));
} else {
thisDevStuff->buttonLogL1->setText(tr("start D-/E-Channel logging"));
}
} else {
bool protoDefined=false;
if (!devInfo->protocol) {
QStringList items;
if (devInfo->Dprotocols & (1 << ISDN_P_TE_S0))
items << "TE mode S0 layer1";
if (devInfo->Dprotocols & (1 << ISDN_P_NT_S0))
items << "NT mode S0 layer1";
if (devInfo->Dprotocols & (1 << ISDN_P_TE_E1))
items << "TE mode E1 layer1";
if (devInfo->Dprotocols & (1 << ISDN_P_NT_E1))
items << "NT mode E1 layer1";
if (devInfo->Dprotocols & (1 << ISDN_P_TE_UP0))
items << "TE mode UP0 layer1";
if (devInfo->Dprotocols & (1 << ISDN_P_NT_UP0))
items << "NT mode UP0 layer1";
QString value = QInputDialog::getItem(this,
tr("select portmode"),
tr("port still unused, please select layer1 mode:"),
items, 0, false, &protoDefined);
if (protoDefined && !value.isEmpty()) {
if (value == "TE mode S0 layer1")
thisDevStuff->l1log->setProtocol(ISDN_P_TE_S0);
if (value == "NT mode S0 layer1")
thisDevStuff->l1log->setProtocol(ISDN_P_NT_S0);
if (value == "TE mode E1 layer1")
thisDevStuff->l1log->setProtocol(ISDN_P_TE_E1);
if (value == "NT mode E1 layer1")
thisDevStuff->l1log->setProtocol(ISDN_P_NT_E1);
if (value == "TE mode UP0 layer1")
thisDevStuff->l1log->setProtocol(ISDN_P_TE_UP0);
if (value == "NT mode UP0 layer1")
thisDevStuff->l1log->setProtocol(ISDN_P_NT_UP0);
}
} else {
thisDevStuff->l1log->setProtocol(devInfo->protocol);
protoDefined = true;
}
if (protoDefined) {
thisDevStuff->eyeSDN.clear();
thisDevStuff->l1log->start();
if (thisDevStuff->l1log->isRunning()) {
QByteArray eyeHeader("EyeSDN");
thisDevStuff->eyeSDN.append(eyeHeader);
if (thisDevStuff->l1log->hasEcho()) {
debugOut(thisDevStuff->log,
tr("D/E channel logging started\n"));
thisDevStuff->buttonLogL1->setText(
tr("stop D-/E-Channel logging"));
}
else {
debugOut(thisDevStuff->log,
tr("D channel logging started\n"));
thisDevStuff->buttonLogL1->setText(
tr("stop D-Channel logging"));
}
} else {
debugOut(thisDevStuff->log,
tr("ERROR: start logging failed\n"));
}
}
}
return 0;
}
int mainWindow::saveL1Log(unsigned int id) {
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(id);
struct mISDN_devinfo * devInfo = getDevInfoById(id);
if ((!thisDevStuff) || (!devInfo))
return -1;
QString filename;
filename = QFileDialog::getSaveFileName(
this, tr("Save Log As WireShark readable"));
// QString("%1").arg(QDir::currentPath()));
if (filename.isEmpty())
return -1;
/* save complete file */
QFile file(filename);
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
for (int i = 0; i < thisDevStuff->eyeSDN.count(); ++i) {
unsigned char byte = thisDevStuff->eyeSDN[i];
out.writeRawData((const char*)&byte, 1);
}
file.close();
return 0;
}
void mainWindow::createNewDeviceTab(struct mISDN_devinfo *devinfo) {
struct isdnDeviceStuff newDevStuff;
qDebug("device %d arised (%s)", devinfo->id, devinfo->name);
newDevStuff.id = devinfo->id;
newDevStuff.tab = new QWidget;
newDevStuff.tabId = tabsheet->addTab(newDevStuff.tab,
QString(devinfo->name));
/* Button 'rename' */
newDevStuff.buttonRename = new idButton(tr("rename"),
newDevStuff.id, newDevStuff.tab);
connect(newDevStuff.buttonRename, SIGNAL(clicked(unsigned int)),
this, SLOT(renameDevice(unsigned int)));
/* Button 'clean Layer2' */
newDevStuff.buttonCleanL2 = new idButton(tr("clean Layer2"),
newDevStuff.id, newDevStuff.tab);
connect(newDevStuff.buttonCleanL2, SIGNAL(clicked(unsigned int)),
this, SLOT(cleanL2(unsigned int)));
/* Button 'L1 logging' */
newDevStuff.buttonLogL1 = new idButton(tr("start D-/E-Channel logging"),
newDevStuff.id, newDevStuff.tab);
connect(newDevStuff.buttonLogL1, SIGNAL(clicked(unsigned int)),
this, SLOT(switchL1Logging(unsigned int)));
/* Button 'saveLog' */
newDevStuff.buttonSaveLog = new idButton(tr("Save Log As"),
newDevStuff.id, newDevStuff.tab);
connect(newDevStuff.buttonSaveLog, SIGNAL(clicked(unsigned int)),
this, SLOT(saveL1Log(unsigned int)));
/* mainLabel */
newDevStuff.mainLabel = new QLabel(QString(tr("Device Controls")));
/* Text Widget */
newDevStuff.log = new QTextEdit();
/* l1log Thread */
newDevStuff.l1log = new Ql1logThread(devinfo->id, misdn);
connect(newDevStuff.l1log, SIGNAL(finished(unsigned int)),
this, SLOT(logFinished(unsigned int)));
connect(newDevStuff.l1log, SIGNAL(rcvData(unsigned int, QByteArray, struct timeval)),
this, SLOT(logRcvData(unsigned int, QByteArray, struct timeval)));
/* Layout */
QVBoxLayout *vbox = new QVBoxLayout(newDevStuff.tab);
vbox->addWidget(newDevStuff.mainLabel);
QHBoxLayout *hbox = new QHBoxLayout();
hbox->addWidget(newDevStuff.buttonRename);
hbox->addSpacing(5);
hbox->addWidget(newDevStuff.buttonCleanL2);
hbox->addSpacing(5);
hbox->addWidget(newDevStuff.buttonLogL1);
hbox->addWidget(newDevStuff.buttonSaveLog);
hbox->insertStretch(5, 0);
vbox->addItem(hbox);
vbox->addWidget(newDevStuff.log);
devStack << newDevStuff;
}
void mainWindow::removeVanishedDevices(void) {
int i, j;
int vanishedDev=1;
while (vanishedDev && devStack.count()) {
for (i=(devStack.count()-1); i>=0; i--) {
vanishedDev = 1;
for (j=0; j<deviceList.count(); j++)
if (devStack[i].id == deviceList[j].id)
vanishedDev = 0;
if (vanishedDev) {
qDebug("device %d vansihed", devStack[i].id);
tabsheet->removeTab(devStack[i].tabId);
for(j=i+1; j<devStack.count(); j++)
devStack[j].tabId--;
devStack.removeAt(i);
break;
}
}
}
}
void mainWindow::renewDeviceWidgets(void) {
int i, j, n = deviceList.count();
struct mISDN_devinfo devinfo;
int newdev;
/* clear old widgets */
devtree->clear();
removeVanishedDevices();
QTreeWidgetItem* devitem;
for (i=0; i<n; i++) {
devinfo = deviceList[i];
newdev = 1;
for (j=0; j<devStack.count(); j++)
if (devinfo.id == devStack[j].id)
newdev = 0;
/* create new Device Tab and stuff */
if (newdev)
createNewDeviceTab(&devinfo);
struct isdnDeviceStuff * thisDevStuff = getStuffbyId(devinfo.id);
if (!thisDevStuff)
return;
/* Update main Device Tree */
devitem = new QTreeWidgetItem(devtree);
devitem->setText(0, QString(devinfo.name));
thisDevStuff->treeHead = devitem;
QTreeWidgetItem* optitem;
optitem = new QTreeWidgetItem(devitem);
optitem->setText(0, tr("Id: %1")
.arg(devinfo.id));
optitem = new QTreeWidgetItem(devitem);
optitem->setText(0, tr("D protocols: %1")
.arg(devinfo.Dprotocols));
if (devinfo.Dprotocols) {
QTreeWidgetItem* l1item = new QTreeWidgetItem(optitem);
l1item->setText(0, tr("Layer 1"));
QTreeWidgetItem* doptitem;
if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0)) {
doptitem = new QTreeWidgetItem(l1item);
doptitem->setText(0, tr("S0 TE"));
}
if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0)) {
doptitem = new QTreeWidgetItem(l1item);
doptitem->setText(0, tr("S0 NT"));
}
if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1)) {
doptitem = new QTreeWidgetItem(l1item);
doptitem->setText(0, tr("E1 TE"));
}
if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1)) {
doptitem = new QTreeWidgetItem(l1item);
doptitem->setText(0, tr("E1 NT"));
}
if (devinfo.Dprotocols & (1 << ISDN_P_TE_UP0)) {
doptitem = new QTreeWidgetItem(l1item);
doptitem->setText(0, tr("UP0 TE"));
}
if (devinfo.Dprotocols & (1 << ISDN_P_NT_UP0)) {
doptitem = new QTreeWidgetItem(l1item);
doptitem->setText(0, tr("UP0 NT"));
}
}
optitem = new QTreeWidgetItem(devitem);
optitem->setText(0, tr("B protocols: %1")
.arg(devinfo.Bprotocols));
if (devinfo.Bprotocols) {
QTreeWidgetItem* l1item = new QTreeWidgetItem(optitem);
l1item->setText(0, QString("Layer 1"));
QTreeWidgetItem* boptitem;
if (devinfo.Bprotocols & (1 <<
(ISDN_P_B_RAW
- ISDN_P_B_START))) {
boptitem = new QTreeWidgetItem(l1item);
boptitem->setText(0,
tr("RAW (transparent)"));
}
if (devinfo.Bprotocols & (1 <<
(ISDN_P_B_HDLC
- ISDN_P_B_START))) {
boptitem = new QTreeWidgetItem(l1item);
boptitem->setText(0, tr("HDLC"));
}
if (devinfo.Bprotocols & (1 <<
(ISDN_P_B_X75SLP
- ISDN_P_B_START))) {
boptitem = new QTreeWidgetItem(l1item);
boptitem->setText(0, tr("X.75"));
}
QTreeWidgetItem* l2item = new QTreeWidgetItem(optitem);
l2item->setText(0, tr("Layer 2"));
if (devinfo.Bprotocols & (1 <<
(ISDN_P_B_L2DTMF
- ISDN_P_B_START))) {
boptitem = new QTreeWidgetItem(l2item);
boptitem->setText(0, tr("DTMF"));
}
}
optitem = new QTreeWidgetItem(devitem);
optitem->setText(0, QString(tr("protocol: %1"))
.arg(devinfo.protocol));
QTreeWidgetItem* l1item = new QTreeWidgetItem(optitem);
switch (devinfo.protocol) {
case 0:
l1item->setText(0, tr("unused"));
break;
case ISDN_P_TE_S0:
l1item->setText(0, tr("S0 TE"));
break;
case ISDN_P_NT_S0:
l1item->setText(0, tr("S0 NT"));
break;
case ISDN_P_TE_E1:
l1item->setText(0, tr("E1 TE"));
break;
case ISDN_P_NT_E1:
l1item->setText(0, tr("E1 NT"));
break;
case ISDN_P_TE_UP0:
l1item->setText(0, tr("UP0 TE"));
break;
case ISDN_P_NT_UP0:
l1item->setText(0, tr("UP0 NT"));
break;
default:
l1item->setText(0, tr("unkown protocol"));
break;
}
optitem = new QTreeWidgetItem(devitem);
optitem->setText(0, tr("B-Channels: %1")
.arg(devinfo.nrbchan));
}
}
void mainWindow::updateDeviceList(void) {
int i, j;
QList <struct mISDN_devinfo> tmpDevList;
int newdev = 0, oldnumdevs = misdn.getLastNumDevs();
i = misdn.getNumDevices();
if (i < 0) {
debugOut(logText, tr("unable to connect mISDN socket\n"));
devtree->clear();
return;
}
if (i != oldnumdevs)
debugOut(logText, tr("found %1 device%2\n")
.arg(i)
.arg((i==1)?"":"s"));
if (i >= 0) {
struct mISDN_devinfo devinfo;
for (j=0; ((j<MAX_DEVICE_ID) && (tmpDevList.count() < i)); j++)
if (misdn.getDeviceInfo(&devinfo, j) >= 0)
tmpDevList << devinfo;
if (tmpDevList.count() == deviceList.count()) {
for (j=0; j<deviceList.count(); j++)
newdev |= memcmp(&tmpDevList[j],
&deviceList[j],
sizeof(struct mISDN_devinfo)-8);
} else
newdev = 1;
/* numDevices of devinfos had changed */
if (newdev) {
deviceList.clear();
for (j=0; j<i; j++) {
debugOut(logText, tr("id %1: '%2'\n")
.arg(tmpDevList[j].id)
.arg(QString(
tmpDevList[j].name)));
deviceList << tmpDevList[j];
}
renewDeviceWidgets();
}
}
}
void mainWindow::debugOut(QTextEdit * textEdit, QString text) {
textEdit->moveCursor(QTextCursor::End);
textEdit->insertPlainText(text);
textEdit->ensureCursorVisible();
}
void mainWindow::binaryOut(QTextEdit * textEdit, QByteArray & data, int offset) {
int i, j=0;
QString lz;
if (offset < data.size())
debugOut(textEdit, ": ");
for (i=offset; i<data.size(); i++) {
lz = (((unsigned char)data[i]) < 0x10)?"0":"";
if (!(j++ % 8))
debugOut(textEdit, "\n\t");
debugOut(textEdit, QString("0x%1%2 ")
.arg(lz)
.arg(QString::number((unsigned char)data[i], 16))
);
}
debugOut(textEdit, "\n\n");
}
void mainWindow::about() {
QMessageBox::information(this,
tr("About qmisdnwatch"),
tr("<b>qmisdnwatch</b> <b>v0.0.1</b><br>m.bachem@gmx.de<br>http://www.misdn.org/index.php/Qmisdnwatch"),
QMessageBox::Ok);
}
void mainWindow::aboutQt() {
QMessageBox::aboutQt(this);
}
// Neue Widget-Klasse vom eigentlichen Widget ableiten
mainWindow::mainWindow( QMainWindow *parent,
Qt::WindowFlags flags ) :
QMainWindow(parent, flags)
{
resize(480, 400);
QWidget * centralwidget = new QWidget(this);
tabsheet = new QTabWidget(centralwidget);
maintab = new QWidget;
tabsheet->addTab(maintab, "mISDN");
QVBoxLayout *vbox01 = new QVBoxLayout(centralwidget);
QVBoxLayout *vbox02 = new QVBoxLayout(maintab);
logText = new QTextEdit(maintab);
logText->setMaximumHeight(120);
devtree = new QTreeWidget(maintab);
devtree->setHeaderLabel(tr("mISDN v2 devices"));
deviceListTimer = new(QTimer);
connect(deviceListTimer, SIGNAL(timeout()),
this, SLOT(updateDeviceList()));
vbox01->addWidget(tabsheet);
vbox02->addWidget(devtree);
vbox02->addWidget(logText);
QMenu * optionsMenu = new QMenu(tr("Options"), this);
// QMenu * actionsMenu = new QMenu(tr("Actions"), this);
QMenu * helpMenu = new QMenu(tr("?"), this);
helpMenu->addAction(tr("about qmisdnwatch"), this, SLOT(about()));
helpMenu->addAction(tr("about Qt"), this, SLOT(aboutQt()));
menuBar()->addMenu(optionsMenu);
// menuBar()->addMenu(actionsMenu);
menuBar()->addMenu(helpMenu);
setCentralWidget(centralwidget);
setWindowTitle(QString ("qmisdnwatch"));
struct mISDNversion v;
v = misdn.getVersion();
debugOut(logText, tr("mISDN kernel driver v%1.%2.%4\n")
.arg(v.major)
.arg(v.minor)
.arg(v.release));
updateDeviceList();
deviceListTimer->start(1000);
}

View File

@ -0,0 +1,94 @@
/* $Id: mainWindow.h 7 2008-10-28 22:06:36Z daxtar $
* (c) 2008 Martin Bachem, m.bachem@gmx.de
*
* This file is part of qmisdnwatch
*
* Project's Home
* http://www.misdn.org/index.php/Qmisdnwatch
*
* qmisdnwatch 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 version 2
*
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef mainWindow_H
#define mainWindow_H
#include <QWidget>
#include <QMainWindow>
#include <QTextEdit>
#include <QTabWidget>
#include <QTreeWidget>
#include <QTimer>
#include <QLabel>
#include <QPushButton>
#include <QThread>
#include <mISDNuser/mISDNif.h>
#include "Ql1logThread.h"
#include "extraWidgets.h"
#include "misdn.h"
struct isdnDeviceStuff {
unsigned int id;
QWidget * tab; /* tab in TabWidget */
int tabId; /* tabID in TabWidget */
QLabel * mainLabel;
QTreeWidgetItem * treeHead;
QTextEdit * log;
idButton * buttonRename;
idButton * buttonCleanL2;
idButton * buttonLogL1;
idButton * buttonSaveLog;
Ql1logThread * l1log;
QByteArray eyeSDN;
};
class mainWindow : public QMainWindow {
Q_OBJECT
public:
mainWindow( QMainWindow *parent = 0,
Qt::WindowFlags flags = 0 );
private:
QList <struct mISDN_devinfo> deviceList;
QList <struct isdnDeviceStuff> devStack;
QTabWidget * tabsheet;
QWidget * maintab;
QTreeWidget * devtree;
QTimer * deviceListTimer;
QTextEdit * logText;
mISDN misdn;
void renewDeviceWidgets(void);
void removeVanishedDevices(void);
void createNewDeviceTab(struct mISDN_devinfo *devinfo);
void debugOut(QTextEdit * textEdit, QString text);
void binaryOut(QTextEdit * textEdit, QByteArray & data, int offset);
struct isdnDeviceStuff * getStuffbyId(unsigned int id);
struct mISDN_devinfo * getDevInfoById(unsigned int id);
void eyeSDNappend(QByteArray & target, QByteArray & data, int offset);
private slots:
void updateDeviceList(void);
int renameDevice(unsigned int id);
int cleanL2(unsigned int id);
int switchL1Logging(unsigned int id);
int saveL1Log(unsigned int id);
void logRcvData(unsigned int id, QByteArray data, struct timeval tv);
int logFinished(unsigned int id);
void about();
void aboutQt();
};
#endif

View File

@ -0,0 +1,173 @@
/* $Id: misdn.cpp 4 2008-10-28 00:04:24Z daxtar $
* (c) 2008 Martin Bachem, m.bachem@gmx.de
*
* This file is part of qmisdnwatch
*
* Project's Home
* http://www.misdn.org/index.php/Qmisdnwatch
*
* qmisdnwatch 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 version 2
*
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "misdn.h"
#define AF_COMPATIBILITY_FUNC
#define MISDN_OLD_AF_COMPATIBILITY
#include <mISDNuser/compat_af_isdn.h>
mISDN::mISDN(void) {
numdevices = -1;
init_af_isdn();
sock = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
if (sock >= 0)
queryVersion();
}
mISDN::~mISDN(void) {
if (sock >= 0) {
close(sock);
}
}
struct mISDNversion mISDN::getVersion(void) {
return(kver);
}
void mISDN::queryVersion(void) {
struct mISDNversion v;
int ret;
if (sock >= 0) {
ret = ioctl(sock, IMGETVERSION, &v);
if (ret >= 0)
memcpy(&kver, &v, sizeof(struct mISDNversion));
}
}
int mISDN::getNumDevices(void) {
int cnt, ret = 0;
if (sock >= 0) {
ret = ioctl(sock, IMGETCOUNT, &cnt);
if (!ret) {
numdevices = cnt;
return(cnt);
}
}
return(-1);
}
int mISDN::getDeviceInfo(struct mISDN_devinfo *devinfo, int id) {
int ret;
if (sock >= 0) {
devinfo->id = id;
try {
ret = ioctl(sock, IMGETDEVINFO, devinfo);
if (!ret)
return 0;
}
catch (...) {
return -1;
}
}
return -2;
}
/*
* returns
* <0 on error
* =0 socket open with no E-Channel logfing available
* =1 socket open with E-Channel logging enabled
*/
int mISDN::openl1Log(int id, int protocol, int * log_socket,
struct sockaddr_mISDN * log_addr)
{
int ret, channel;
if ((*log_socket = socket(PF_ISDN, SOCK_DGRAM, protocol)) >= 0)
{
log_addr->family = AF_ISDN;
log_addr->dev = id;
ret = -1;
channel = 1;
while ((ret < 0) && (channel >= 0)) {
log_addr->channel = (unsigned char)channel;
ret = bind(*log_socket, (struct sockaddr *)log_addr,
sizeof(struct sockaddr_mISDN));
if (ret < 0)
channel--;
}
int opt=1;
setsockopt(*log_socket, SOL_MISDN, MISDN_TIME_STAMP,
&opt, sizeof(opt));
return (log_addr->channel == 1);
}
return -1;
}
int mISDN::getLastNumDevs(void) {
return(numdevices);
}
int mISDN::renameLayer1(unsigned int id, char * name) {
struct mISDN_devrename devrename;
int ret;
if (sock >= 0) {
devrename.id = id;
strncpy(devrename.name, name, MISDN_MAX_IDLEN);
ret = ioctl(sock, IMSETDEVNAME, &devrename);
return ret;
}
return -1;
}
int mISDN::cleanl2(unsigned int id) {
int ret;
if (sock >= 0) {
struct mISDN_devinfo devinfo;
if (getDeviceInfo(&devinfo, id) >= 0) {
if (!devinfo.protocol)
return -4;
int l2sock;
if (IS_ISDN_P_TE(devinfo.protocol))
l2sock = socket(PF_ISDN, SOCK_DGRAM,
ISDN_P_LAPD_TE);
else
l2sock = socket(PF_ISDN, SOCK_DGRAM,
ISDN_P_LAPD_NT);
if (l2sock >= 0) {
struct sockaddr_mISDN addr;
addr.family = AF_ISDN;
addr.dev = id;
addr.channel = 0;
addr.sapi = 0;
addr.tei = 127;
ret = bind(l2sock, (struct sockaddr *) &addr,
sizeof(addr));
if (ret >= 0) {
int clean = 1;
ret = ioctl(l2sock, IMCLEAR_L2, &clean);
if (ret < 0)
return -1;
return 0;
} else
return -2;
} else
return -3;
} else
return -6;
}
return -7;
}

View File

@ -0,0 +1,102 @@
/* $Id: misdn.h 6 2008-10-28 19:50:12Z daxtar $
* (c) 2008 Martin Bachem, m.bachem@gmx.de
*
* This file is part of qmisdnwatch
*
* Project's Home
* http://www.misdn.org/index.php/Qmisdnwatch
*
* qmisdnwatch 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 version 2
*
* qmisdnwatch 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 qmisdnwatch. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _MISDN_H_
#define _MISDN_H_
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/udp.h>
#include <netinet/in.h>
#include <netdb.h>
#include <linux/socket.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <mISDNuser/mISDNif.h>
#include <mISDNuser/q931.h>
#ifndef ISDN_P_TE_UP0
#define ISDN_P_TE_UP0 0x05
#endif
#ifndef ISDN_P_NT_UP0
#define ISDN_P_NT_UP0 0x06
#endif
#ifndef IS_ISDN_P_TE
#define IS_ISDN_P_TE(p) ((p == ISDN_P_TE_S0) || (p == ISDN_P_TE_E1) || \
(p == ISDN_P_TE_UP0) || (p == ISDN_P_LAPD_TE))
#endif
#ifndef IS_ISDN_P_NT
#define IS_ISDN_P_NT(p) ((p == ISDN_P_NT_S0) || (p == ISDN_P_NT_E1) || \
(p == ISDN_P_NT_UP0) || (p == ISDN_P_LAPD_NT))
#endif
#ifndef IS_ISDN_P_S0
#define IS_ISDN_P_S0(p) ((p == ISDN_P_TE_S0) || (p == ISDN_P_NT_S0))
#endif
#ifndef IS_ISDN_P_E1
#define IS_ISDN_P_E1(p) ((p == ISDN_P_TE_E1) || (p == ISDN_P_NT_E1))
#endif
#ifndef IS_ISDN_P_UP0
#define IS_ISDN_P_UP0(p) ((p == ISDN_P_TE_UP0) || (p == ISDN_P_NT_UP0))
#endif
class mISDN {
public:
mISDN(void);
~mISDN(void);
int getNumDevices(void);
int getDeviceInfo(struct mISDN_devinfo *devinfo, int id);
int getLastNumDevs(void);
struct mISDNversion getVersion(void);
/* socket helper */
int openl1Log(int id, int protocol, int * log_socket,
struct sockaddr_mISDN * log_addr);
/* tools / examples */
int renameLayer1(unsigned int id, char * name);
int cleanl2(unsigned int id);
private:
void queryVersion(void);
int numdevices; // devicesNumber
int sock; // base socket handles
struct mISDNversion kver; // mISDN kernel version
};
struct ctstamp {
size_t cmsg_len;
int cmsg_level;
int cmsg_type;
struct timeval tv;
};
#endif // _MISDN_H_