Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

use Perl With usblp Parallel Adapter

by Morzilla (Novice)
on Oct 03, 2009 at 10:51 UTC ( [id://798993]=perlquestion: print w/replies, xml ) Need Help??

Morzilla has asked for the wisdom of the Perl Monks concerning the following question:

Hello Everyone! can someone help me with this problem:

I Bought an usb-to-parallel port adapter (lsusb give me Bus 001 Device 002: ID 067b:2305 Prolific Technology, Inc. PL2305 Parallel Port), and Linux recognize it as /dev/usb/lp0

dmesg:
[ 35.125223] usblp0: USB Bidirectional printer dev 2 if 0 alt 1 prot +o 2 vid 0x067B pid 0x2305 [ 35.125307] usbcore: registered new interface driver usblp
now the problem: both the modules Device::ParallelPort::drv::parport and Device::ParallelPort::drv::linux that i tried in perl gave me this error for the first module:
Device::ParallelPort unabel to create driver parport (see Device::Para +llelPort::drv::auto for further information) - Failed to load partpor +t driver for /dev/usb/lp0 at (eval 1) line 3 at ./parportcontroller line 5
and this for the second:
Use of uninitialized value in subroutine entry at /usr/local/lib/perl/ +5.10.0/Device/ParallelPort/drv/linux.pm line 68.
I Tried to hard code in the second module the device character file at line 68
$this->{DATA}{BASE} = linux_opendev("/dev/usb/lp0");
but this didn't work, the result is that my script doesn't set or get any bit from the parallel port. Here is my code:
#!/usr/bin/perl -w use Device::ParallelPort; my $port = Device::ParallelPort->new('linux'); if($port){ print "Bit 0: ".$port->get_bit(1)."\n"; $port->set_bit(1, 0); print "Bit 0: ".$port->get_bit(1)."\n"; } else { die "Errore sul driver\n"; }
and this is the result:
Use of uninitialized value in subroutine entry at /usr/local/lib/perl/ +5.10.0/Device/ParallelPort/drv/linux.pm line 68. Bit 0: 1 Bit 0: 1
The Device::ParallelPort::drv::parport module give me the error above. Someone can help me? Thanks, and sorry for my bad english XD

Replies are listed 'Best First'.
Re: use Perl With usblp Parallel Adapter
by almut (Canon) on Oct 03, 2009 at 12:05 UTC

    I might be telling you the obvious... but have you checked that you actually have access to the device?  Which user are you running this as?  Can you send stuff to the device from the commandline (e.g. "echo foo >/dev/usb/lp0")?

    For example, on my machine (Ubuntu), the /dev/usb/lp0  is being created as  (for example when I plugin my printer):

    $ ls -l /dev/usb/lp0 crw-rw---- 1 root lp 180, 0 2009-10-03 13:35 /dev/usb/lp0

    but I'm not in group lp (by default), so I cannot access the device as my regular user. This is on purpose, because I'm not supposed to access the device directly, but rather go via the appropriate printing machinery, such as cupsd and friends.

      Thank you for the answer. Yes, I'm root on the machine where I run the script. This is the permissions of the special character device /dev/usb/lp0:
      crw-rw---- 1 root lp 180, 0 Oct 3 13:14 /dev/usb/lp0
      and yes, I can write into the device
      pbx:/usr/local/share/router# echo "test" > /dev/usb/lp0 pbx:/usr/local/share/router#
      I'm using Debian Lenny. Thank you again.
Re: use Perl With usblp Parallel Adapter
by almut (Canon) on Oct 03, 2009 at 15:47 UTC

    Ok, I just played around with this a bit... (never had used the module before).

    It seems you can ignore the "uninitialized value" warning. It originates from accessing $this->{DATA}{DEVICE} in Device::ParallelPort::drv::linux::init(), where the hash entry DEVICE is undefined — which isn't too surprising, as it isn't being set anywhere in the entire code (and AFAICT you can't set it by passing some value to the constructor, or some such). And when you dig a bit into the XS code, you'll find that it should be a device name (string). OTOH, that name is only ever being used in an error message you'd see in case the device initialisation should fail...

    Anyhow, to get rid of the "uninitialized value", you could add

    sub init { my ($this, $str, @params) = @_; $this->{DATA}{DEVICE} = "lp0"; # <--- $this->{DATA}{BASE} = linux_opendev($this->{DATA}{DEVICE}); ...

    to the init() routine in Device/ParallelPort/drv/linux.pm  (the base address of lp0 (i.e. 0x378) is hardcoded anyway).

    Other than that, the module seems to work here (I am using the USB parallel port device), i.e. with the following test code

    #!/usr/bin/perl -w use Device::ParallelPort; my $port = Device::ParallelPort->new('linux'); if($port){ $port->set_data(chr(0)); $port->set_control(chr(0)); show("Data", $port->get_data()); show("Control", $port->get_control()); show("Status", $port->get_status()); print "set bit 0 to 0\n"; $port->set_bit(0, 0); printf "read bit 0: %d\n", $port->get_bit(0); print "set bit 0 to 1\n"; $port->set_bit(0, 1); printf "read bit 0: %d\n", $port->get_bit(0); print "set bit 0 to 0\n"; $port->set_bit(0, 0); printf "read bit 0: %d\n", $port->get_bit(0); print "set bit 2 to 1\n"; $port->set_bit(2, 1); printf "read bit 2: %d\n", $port->get_bit(2); show("Data", $port->get_data()); print "set data 'a' (0x61 01100001)\n"; $port->set_data('a'); show("Data", $port->get_data()); print "set control 4 (bit 2)\n"; $port->set_control(chr(4)); show("Control", $port->get_control()); show("Status", $port->get_status()); } else { die "Errore sul driver\n"; } sub show { my $portname = shift; my $val = ord shift; printf "%-13s %02x %08b\n", "$portname port:", $val, $val; }

    I do get

    Data port: 00 00000000 Control port: c0 11000000 Status port: 7f 01111111 set bit 0 to 0 read bit 0: 0 set bit 0 to 1 read bit 0: 1 set bit 0 to 0 read bit 0: 0 set bit 2 to 1 read bit 2: 1 Data port: 04 00000100 set data 'a' (0x61 01100001) Data port: 61 01100001 set control 4 (bit 2) Control port: c4 11000100 Status port: 7f 01111111

    which kinda makes sense... (the upper two bits of the control port apparently are static — at least with my hardware)

      Thanks. I modified the Device::ParallelPort::drv::linux module, and in the init() function I added the code:
      $this->{DATA}{DEVICE} = "lp0";
      before the "linux_opendev" call, but the result is the same: I can't set (and probably get) the data bits (this is the result of your script almut):
      Data port: ff 11111111 Control port: ff 11111111 Status port: ff 11111111 set bit 0 to 0 read bit 0: 1 set bit 0 to 1 read bit 0: 1 set bit 0 to 0 read bit 0: 1 set bit 2 to 1 read bit 2: 1 Bit 0: 1 Data port: ff 11111111 set data 'a' (0x61 01100001) Data port: ff 11111111 set control 4 (bit 2) Control port: ff 11111111 Status port: ff 11111111
      I tried to change "lp0" in this->{DATA}{DEVICE} to "/dev/usb/lp0", but nothing changed... I think that my usb adapter is not so compatible with Linux or maybe it's not a really usb to parallel port adapter...
        I tried to change "lp0" in this->{DATA}{DEVICE} to "/dev/usb/lp0", but nothing changed...

        As I said, that value is only ever being used in an error message. The purpose behind setting it was just to silence the warning...

        I think that my usb adapter is not so compatible with Linux or maybe it's not a really usb to parallel port adapter...

        Either that, or it isn't mapped to the I/O address 0x378 (which is hardcoded in Device::ParallelPort::drv::linux::linux_opendev() ).  The code in question is:

        ... base = 0x378; if (ioperm(base, LPSIZE, 1) < 0) { fprintf(stderr, "%s: ioperm:%s ", devname, strerror(errno) +); RETVAL = -1; } else { RETVAL = base; }

        ioperm(2) can only fail with

        EINVAL Invalid address(-range). EPERM The calling process has insufficient privilege. ENOMEM Out of memory. EIO This call is not supported (on PowerPC).

        In particular, no checks are being made that the address actually maps to the intended hardware device.

        You might want to check your dmesg output — mine, for example, says:

        [ 61.718702] parport_pc 00:0b: reported by Plug and Play ACPI [ 61.718797] parport0: PC-style at 0x378, irq 7 [PCSPP,TRISTATE] [ 63.870838] lp0: using parport0 (interrupt-driven).
Re: use Perl With usblp Parallel Adapter
by kikuchiyo (Hermit) on Oct 03, 2009 at 13:26 UTC
    Chances are that it won't work.

    I think Device::ParallelPort needs an actual, physical parallel port to work, that is to give you low level access to its bits.

    A USB parallel port emulator just pretends to be a parallel port, but in reality it isn't one.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://798993]
Approved by Perlbotics
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (2)
As of 2024-04-20 04:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found