in reply to use Perl With usblp Parallel Adapter

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)

Replies are listed 'Best First'.
Re^2: use Perl With usblp Parallel Adapter
by Morzilla (Novice) on Oct 04, 2009 at 11:59 UTC
    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).