PDA

View Full Version : Parallel Interface



r00tz
10th February 2006, 02:28
Does anyone can help me how to interface Qt with parallel port? I'm developing a software that sends some commands to the parallel. Wich class may I use? Thanks

zlatko
10th February 2006, 09:40
Does anyone can help me how to interface Qt with parallel port? I'm developing a software that sends some commands to the parallel. Wich class may I use? Thanks

i'm not sure but i think that qt cant help you with it, you must use standart api approach:rolleyes:

high_flyer
10th February 2006, 10:12
For which platform?
I implemented a basic Qt wrapped for parapin (the paraport driver for linux) if you want it I can post it.

Cesar
10th February 2006, 10:57
I guess you should create a subclass of QIODevice and implement all the platform-specific issues by yourself :( Something like this:


//ParalellPort.h
#include <QIODevice>

class ParalellPort : public QIODevice {
Q_OBJECT
public:
ParalellPort(const QString &, QObject * = 0);
virtual ~ParalellPort();

virtual bool isSequential () const { return true; }

virtual bool open(OpenMode);
virtual void close ();
//..
protected:
virtual qint64 readData ( char * data, qint64 maxSize );
virtual qint64 writeData ( const char * data, qint64 maxSize );
private:
#ifdef Q_OS_UNIX
QFile deviceFile;
#endif
};

//ParalellPort.cpp
#include "ParalellPort.cpp"

ParalellPort::ParalellPort(const QString & port, QObject * parent) :
QIODevice(parent)
#ifdef Q_OS_UNIX
, deviceFile(port)
#endif
{
}

bool ParalellPort::open(OpenMode mode) {
#ifdef Q_OS_UNIX
return deviceFile.open(mode);
#endif

#ifdef Q_OS_MACX
//...
#endif

#ifdef Q_OS_WIN32
//...
#endif
}
//...

A quote from TT's docs:

Subclasses of QIODevice are only required to implement the protected readData() and writeData() functions.

high_flyer
10th February 2006, 12:10
I guess you should create a subclass of QIODevice
Well, yes and no.
The 'problem' with the parallel port is that you can (and usually want to) manipulate individual pins. not just (or nesseseraly) transmit data.

Cesar
10th February 2006, 12:29
Well, yes and no.
The 'problem' with the parallel port is that you can (and usually want to) manipulate individual pins. not just (or nesseseraly) transmit data.


void ParalellPort::setPin(int pin, int value)
{
int oldValue = getChar(pin);
if (value != 0) {
putChar(oldValue | 1 << pin);
} else {
putChar(oldValue & (~ (1 << pin)) );
}
}

int ParalellPort::getPin(int pin)
{
return (getChar() & (1 << pin)) ? 1 ? 0;
}

high_flyer
10th February 2006, 12:40
Ok, here is my implementation, at the moment the fact its Qt has no advantage.
One could build in a polling mechanism that will send signals on pin state changes.
This clas works, it is being used in a program that controlls harware through the paraport.
You should install parapin and read the docs there.

r00tz
10th February 2006, 22:45
Well... I'd just like to thank both of you. This helped very very much, I got some tutorial about parallel port interfacing. With all code and tips you passed to me, I will implement it. Thanks a lot.

wallyqt
13th November 2007, 11:58
I tried the parapin drivers and it works good as root.
When using the parapin-kernel-driver i can access the port from user-space.
Do anybody know how to implement the kerneldriver with qt.
I am looking for something very similar "QParaport.zip" from "high_flyer".

I able to open the parapindriver with:
(set pins is also possible:
int kparappWidget::pushButtonOpen_clicked()
{
pardevice = open("/dev/ppdrv_device", 0);
if (pardevice < 0) {
fprintf(stderr, "pardevice open failed\n");
exit(-1);
}
return 0;
}

but when i call the close function, all widgets on the application mainWin
disappear and i only can close (kill) the app.

int kparappWidget::pushButtonClose_clicked()
{
close(pardevice);
return 0;
}

here is the code for setting pins:

void kparappWidget::pushButtonSetPins_clicked()
{
ioctl(pardevice, PPDRV_IOC_PINMODE_OUT, LP_PIN02);

ioctl(pardevice, PPDRV_IOC_PINSET, LP_PIN02 | LP_PIN03 | LP_PIN04 | LP_PIN05 | LP_PIN06 | LP_PIN07 | LP_PIN08 | LP_PIN09);
}

cheers wally

high_flyer
13th November 2007, 12:42
I tried the parapin drivers and it works good as root.
When using the parapin-kernel-driver i can access the port from user-space.
I am not sure you mean what your text says. i.e:
Do you mean you want to use the kernel module from user space, or, do you want to use the user space module with a user that is not root?

It could be that you have problem with read write right for non root users, you can fix that with chmod.

You can't use the kernel module from user space (and you shouldn't)
And if you don't need PIN10, (and from your code it seams that way) you don't need to - the user space module should be used - and you can the QParaport class for what you described here.

wallyqt
13th November 2007, 13:04
high_flyer,

you are right, its confusing because i didn't understand it myself not entirely.
I want to use the kernel-driver of parapin which i load during boot.
After the driver is once loaded i do not want to use root anymore.

In command-line apps it works perfect, but i have problems to close the
device properly in a kde-qt-app.

i think i should use Qiodevice.h and not mixing old and new stuff together,
but i am not a good programmer. So i ask in this forum.

As far as i understand you code sample - it needs root previleges.
But i want to use the parapin stuff also in a larger application which not should run as root.

Maybe i do some fundamnetal error

cheers wally

high_flyer
13th November 2007, 13:18
I want to use the kernel-driver of parapin which i load during boot.
No, you want to use the user space module ;)
Only the system is allowed to access the kernel space module.
Read the parapin documentation (http://parapin.sourceforge.net/doc/parapin.html).

The problem with QParaport is that it is written for Qt3.
And I haven't had a look at this code for a very long time, so I don't know how easy it should be to port it to Qt4. (I forgot about this during the last post)
But I think it should be just a matter of changing the header deceleration.


As far as i understand you code sample - it needs root privileges.
The *code* doesn't require root privileges.
Under linux, you can set access privileges using the chmod command.
read the chmod command man pages for usage. (its simple)


i think i should use Qiodevice.h and not mixing old and new stuff together,
QIOdevice could be good if you'd want to implement the driver your self.
But if you use the ready made parapin driver, all you can do is either wrap it (as I did with QParaport) or use it directly.
It has nothing to do with mixing new and old.

wallyqt
13th November 2007, 13:42
high_flyer

Thanks for your patience and explanation.

Any concrete idea what i could do to find the problem
with close(device) function in the code above.

Gnu debugger and system messages do not have
any interesting outputs on this problem.

cheers wally

high_flyer
13th November 2007, 13:47
yes - use the user space module.
You should not access kernel space from user space.

wallyqt
13th November 2007, 13:59
No, you want to use the user space module ;)
Only the system is allowed to access the kernel space module.
.


yes - use the user space module.
.


I think using the above code i do so hm ?
(now i am completely confused)

cheers wally

high_flyer
13th November 2007, 14:10
read the parapin user documentation in the link I posted before on this thread.
Specifically look for the section:
"Parapin Basics
Userspace version and kernel version "

wallyqt
13th November 2007, 14:41
high_flyer

for me the parapin documentation sounds as follows:
There is a C library version and a Kernel Module version with a device driver.

Quotes from parapin documentation:

C library version:
Programs using Parapin must be running as root when they are initialized.

Kernel-Module version:
Before the parapindriver device interface may be used, an entry in /dev must be created that corresponds to the device driver module loaded in to the kernel

Once parapindriver is successfully loaded, and a corresponding /dev entry is in place, initialization and shutdown of the parallel port are easy. To initialize the parapin system, just call open(2) on the /dev entry as you would any other device file:

int device;
device = open("/dev/<device-name>", 0);

if (device < 0) {
fprintf(stderr, "device open failed\n");
exit(-1);
}

To shutdown the parapin system you simply have to call close(2):

close(device);


I want to use the last one and excepting the "close(device) everything is ok.


cheers wally

high_flyer
14th November 2007, 11:23
Ok, I see what you mean.
It has been quite long since I used this, so I guess I need to read the docs again ;)

Did you do what is says in the docs about initializing the driver?


int pin_init_kernel(int lpt, void (*irq_func)(int, void *, struct pt_regs *));
AND :
void pin_release();

wallyqt
14th November 2007, 11:57
high_flyer

No, because afaik this is the initialization for the C-library version.
During boot my system do the following (of course as root) :


DEVNAME="ppdrv_device"
depmod
modprobe kparapin
modprobe parapindriver devname=${DEVNAME}
mknod /dev/${DEVNAME} u `grep $DEVNAME /proc/devices | cut -d " " -f 1` 0
# Change mode and ownership here if necessary
chmod 777 /dev/${DEVNAME}
chown root /dev/${DEVNAME}
chgrp root /dev/${DEVNAME}

After this is done i acces the parapellport (as user) by opening the device:

pardevice = open("/dev/ppdrv_device", 0);
if (pardevice < 0) {
fprintf(stderr, "pardevice open failed\n");
exit(-1);

from this point on i can simply acces the parallelport with the ioctl command, e.g.:

ioctl(pardevice, PPDRV_IOC_PINMODE_OUT, LP_PIN02);
ioctl(pardevice, PPDRV_IOC_PINSET, LP_PIN02 | LP_PIN03)

I preferred this because i added some parts to the KSIMUS Application.
Its a Electronics simulator by Rasmus Diekenbrock.
I want to avoid the need of root access during the simulator is accessing
the parallelport. It works perfect in KSIMUS (also the close(device) command
which is the reason i wrote here.

In a simple new Kdevelop project, just for open the device,
setting some pins and close the device, this mini application
doesn't work as expected.

When i call "close(device" all of the widgets ( 3 pushbuttons for open/set/close)
disappear and thats it. I have to kill the process.

I wrote here in QT-Centre because i think its not a problem of parapin.
Parapin works perfect e.g. in the ksimus enveronment.

I am sure i am making some coding or logical errors in my code.
( maybe the close(device) command from unistd.h is not welcome.

Also some hint is desireable how to trace what is going on in the app
after calling close(device) and the "crash"

"gdb" and the system messages do not contain strange infos on this.

cheers wally

high_flyer
14th November 2007, 12:34
No, because afaik this is the initialization for the C-library version.
read again:


The Kernel Module Version

Initialization and shutdown in the kernel flavor of Parapin is done using the following two functions:

int pin_init_kernel(int lpt,
void (*irq_func)(int, void *, struct pt_regs *));
void pin_release();

The first function is not as intimidating as it looks. Its first argument, lpt, is the parallel port number that you want to control. The number references the kernel's table of detected parallel ports; 0 is the first parallel port and is a safe guess as a default.

The second argument, irq_func, is a pointer to a callback function to be used for servicing interrupts generated by the parallel port. This argument may be NULL if the driver does not need to handle interrupts. Details about interrupt handling are discussed in Section 9.

pin_init_kernel will return 0 on success, or a number less than 0 on error. The return value will be a standard errno value such as -ENODEV, suitable for passing up to higher layers. If Parapin initialization fails, the driver must not call Parapin's other functions. As described earlier, this requirement is not enforced for efficiency reasons.

When a driver is finished controlling the parallel port using Parapin, it must call pin_release. The state of the parallel port's interrupt-enable bit will be restored to the state it was in at the time pin_init_kernel was originally called.

Parapin's pin_init_kernel and pin_release functions work with the Linux kernel's standard parport facility; as noted above, the parport module must be loaded along with any module that uses Parapin. When initialized, Parapin will register itself as a user of the parallel port, and claim exclusive access to that port. This means no other processes will be allowed to use the parallel port until pin_release is called.

wallyqt
14th November 2007, 13:25
high_flyer

int pin_init_kernel(int lpt,
void (*irq_func)(int, void *, struct pt_regs *));
void pin_release();

All this stuff, especially "pin_init_kernel" is contend of "kparapin" and "parapindriver",
which i successfully compiled and "moddprobe" inserted seperately before.

All this is running. I can open the device, setting and clear all pins.
In a command line application and in ksimus i can even close it without any trouble.

Everything is nice except the close(device) command in a primitiv kde application
i tried to build.
Just this my problem.

cheers wally :)

high_flyer
14th November 2007, 13:57
hmm...
did you check the standard error after open()?

wallyqt
14th November 2007, 14:00
i just put a Messagebox behind the critical close(device) instruction
and achieved a nice crash with backtrace-log.
Maybe this could clear the situation:

int kparappWidget::pushButtonClose_clicked()
{
close(pardevice);
QMessageBox::about(this, tr("About Application"),
tr("The <b>Application</b> example demonstrates how to "
"write modern GUI applications using Qt, with a menu bar, "
"toolbars, and a status bar."));

return 0;
}

Backtrace log after crash:

System configuration startup check disabled.

Using host libthread_db library "/lib/libthread_db.so.1".
[Thread debugging using libthread_db enabled]
[New Thread 0xb6cf36d0 (LWP 21378)]
[KCrash handler]
#9 0xb6e21228 in main_arena () from /lib/libc.so.6
#10 0xb7461440 in QObject::QObject () from /usr/lib/qt3/lib/libqt-mt.so.3
#11 0xb749741d in QWidget::QWidget () from /usr/lib/qt3/lib/libqt-mt.so.3
#12 0xb75e7852 in QDialog::QDialog () from /usr/lib/qt3/lib/libqt-mt.so.3
#13 0xb7612c70 in QMessageBox::QMessageBox ()
from /usr/lib/qt3/lib/libqt-mt.so.3
#14 0xb7612d59 in QMessageBox::about () from /usr/lib/qt3/lib/libqt-mt.so.3
#15 0x0804ec16 in kparappWidget::pushButtonClose_clicked (this=0x80eb560)
at /home/op/sda-2/Programming/kdevelop-work/kparapp/src/kparappwidget.cpp:82
#16 0x0804f23a in kparappWidgetBase::qt_invoke (this=0x80eb560, _id=48,
_o=0xbfc780a8) at ./src/kparappwidgetbase.moc:104
#17 0x0804e999 in kparappWidget::qt_invoke (this=0x80eb560, _id=48,
_o=0xbfc780a8) at ./src/kparappwidget.moc:108
#18 0xb7460f1d in QObject::activate_signal ()
from /usr/lib/qt3/lib/libqt-mt.so.3
#19 0xb7461b5d in QObject::activate_signal ()
from /usr/lib/qt3/lib/libqt-mt.so.3
#20 0xb77a3b5c in QButton::clicked () from /usr/lib/qt3/lib/libqt-mt.so.3
#21 0xb74f4bfd in QButton::mouseReleaseEvent ()
from /usr/lib/qt3/lib/libqt-mt.so.3
#22 0xb7499880 in QWidget::event () from /usr/lib/qt3/lib/libqt-mt.so.3
#23 0xb74019c7 in QApplication::internalNotify ()
from /usr/lib/qt3/lib/libqt-mt.so.3
#24 0xb7402909 in QApplication::notify () from /usr/lib/qt3/lib/libqt-mt.so.3
#25 0xb7b7dd32 in KApplication::notify () from /opt/kde3/lib/libkdecore.so.4
#26 0xb73a0f57 in QETWidget::translateMouseEvent ()
from /usr/lib/qt3/lib/libqt-mt.so.3
#27 0xb73a00ff in QApplication::x11ProcessEvent ()
from /usr/lib/qt3/lib/libqt-mt.so.3
#28 0xb73b098a in QEventLoop::processEvents ()
from /usr/lib/qt3/lib/libqt-mt.so.3
#29 0xb74187f0 in QEventLoop::enterLoop () from /usr/lib/qt3/lib/libqt-mt.so.3
#30 0xb7418686 in QEventLoop::exec () from /usr/lib/qt3/lib/libqt-mt.so.3
#31 0xb740157f in QApplication::exec () from /usr/lib/qt3/lib/libqt-mt.so.3
#32 0x0804dec2 in main (argc=134547724, argv=0xb6e212e2)
at /home/op/sda-2/Programming/kdevelop-work/kparapp/src/main.cpp:69


cheers wally

high_flyer
14th November 2007, 14:08
Is this a Qt3 application?
And is the message executed?

wallyqt
14th November 2007, 14:10
hmm...
did you check the standard error after open()?


pardevice = open("/dev/ppdrv_device", O_RDWR);
if (pardevice < 0) {
fprintf(stderr, "pardevice open failed\n");
return -1;
}

Yes, if there would be a problem, i would not be able to set and clear pins.
At least i assume so.

cheers wally

wallyqt
14th November 2007, 14:18
Is this a Qt3 application?
And is the message executed?

Its an qt3 application, because my environment is setu to
manipulate the old ksimus code.

The Messagbox does not appear!

The optical effect is now, that the widgets do not disappear
but the pushbutton which triggers the close(device) instruction
remains pushed (do not come back, not released again).
and the application is frozen.

high_flyer
14th November 2007, 14:25
what happens if you just comment the ioctl calls?
(I know that the pin manipulation wont work)
Does it crash then too?

wallyqt
14th November 2007, 14:34
(I know that the pin manipulation wont work)


:D

Yes it crashes too!

just the open (device ......... and the close( device .....

its only the close instruction i guess.

I will try to make a fresh new app for qt4 and see whats happens there.

wallyqt
14th November 2007, 15:28
high_flyer

i posted a request to the parapin mailinglist during the last discussion:

quote: wallyqt:

Would be nice if somebody more experienced than me
may help to clear some missunderstandings on parapin.
discussion on QT-Centre:
http://www.qtcentre.org/forum/f-qt-programming-2/t-parallel-interface-594.html

quote:parapin-users@lists.sourceforge.net :Al Houston:

**Wally,
********I just read through your thread on Qt-Centre, it looks like you guys
have it figured out correctly by the end of the thread. *The fact this
is working as a console app, but not a Qt app, is important.

********I'm not a Qt programmer, but I have one question: Does Qt mess around
with loading/unloading kernel modules under the hood at all? *If for
some reason it forced an unload of kparapin or parport, you might get
the crash you're seeing on close(). *Seems very unlikely to me, but I
thought I'd mention it.

********I've just gone through the code again -- I can't see any reason why a
gui layer like Qt would have any idea what's going on in a driver, or
have any effect on it.

********This is a strange one... *I probably won't have time to look at this
anymore for the next several days, at least. *Hopefully you guys will
get it figured out by then.


-Al

wallyqt
19th November 2007, 09:52
high_flyer

i did the same stuff with qt4 and at least achieved an readable error:

qtparapinwidgets.cpp:68: error: no matching function for call to ‘QtParapinWidgets::close(int&)’
/usr/include/QtGui/qwidget.h:444: note: candidates are: bool QWidget::close()


cheers wally

wallyqt
19th November 2007, 12:35
when i use the ::close for the general namespace i get the
same crash as with Qt3 :(

any ideas ?

#include <fcntl.h> /* open, fcntl */
#include <sys/ioctl.h> /* ioctl */
#include <stdio.h> /* printf, getchar */
#include <stdlib.h> /* exit */
#include <parapindriver.h> /* parapindriver */
#include <unistd.h> /* close, read, usleep */
#include <iostream>

void QtParapinWidgets::on_pushButtonClose_clicked()
{
qWarning("TODO: %s %d",__FILE__,__LINE__);

if ( m_parapinloaded == true)
{
::close(parapindevice);
m_parapinloaded = false;
// label->setText( "Device Closed" );
}
}


wally
}

wallyqt
19th November 2007, 12:50
Now it works fine! :)

when i also use ::open to open the device
i can ::close and all works as wanted.

parapindevice = ::open("/dev/ppdrv_device", 0);

cheers wally