Recent

Author Topic: Reading from /dev/usb/lp0 device on Linux  (Read 2479 times)

dogriz

  • Full Member
  • ***
  • Posts: 126
Reading from /dev/usb/lp0 device on Linux
« on: September 25, 2020, 11:15:30 am »
I can send commands and print data to a USB barcode printer (Sanei SK1-21) using code like this:
Code: Pascal  [Select][+][-]
  1. fs := TFileStream.Create('/dev/usb/lp0', fmCreate);
  2. fs.WriteBuffer(something[1], Length(something));
  3. fs.Free;
and it works without a problem.

When I want to check printer status (waiting, error, near end, paper empty...) I send matching command using the code above, then free the FileStream, open it for reading like this:
Code: Pascal  [Select][+][-]
  1. fs := TFilestream.Create('/dev/usb/lp0', fmOpenRead, fmShareDenyNone);
  2. fs.ReadBuffer(buf, SizeOf(buf));
  3. fs.Free;
and get a response (for example: R000) and use it as wanted.

But, from time to time, it happens that there is nothing to be read in '/dev/usb/lp0' (same happens if I don't send request for status first, before trying to read it) and that's also OK. The only thing that troubles me is - when there is nothing to be read in '/dev/usb/lp0', this line: fs.ReadBuffer(buf, SizeOf(buf)); hangs forever and I can't do anything anymore with '/dev/usb/lp0' because it's locked. I don't even get any error message, it's just stuck.

Is there some kind of TimeOut setting or something for TFileStream.ReadBuffer or other way to deal with this issue?
FPC 3.2.2
Lazarus 2.2.4
Debian x86_64, arm

Kays

  • Hero Member
  • *****
  • Posts: 569
  • Whasup!?
    • KaiBurghardt.de
Re: Reading from /dev/usb/lp0 device on Linux
« Reply #1 on: September 25, 2020, 02:53:29 pm »
[…] Is there some kind of TimeOut setting or something for TFileStream.ReadBuffer or other way to deal with this issue?
Well, select? Or its FP wrapper fpSelect? But I’m not familiar with tFileStream, so I can’t tell you nothing about that.
Yours Sincerely
Kai Burghardt

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Reading from /dev/usb/lp0 device on Linux
« Reply #2 on: September 25, 2020, 03:44:09 pm »
I am not at all an expert on stream access, and I don't even know whether it supports polling for available data (which is more of a "keyboard-like" operation). You've obviously got to allow for the fact that the device name might change (or the device disappear) depending on hotplug events, but I think there are two possibilities:

Either have a separate thread which spends most of its time waiting for input from that device and when it knows it's got an entire message writes it to a shared variable,

Or replace your existing code with direct access to lower-level calls (fpRead() etc.), since that will allow you to use fpSelect() with a zero or nil timeout, or an fpIoctl() call, to determine whether the next read will block.

MarkMLl

 
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

dogriz

  • Full Member
  • ***
  • Posts: 126
Re: Reading from /dev/usb/lp0 device on Linux
« Reply #3 on: September 28, 2020, 08:08:38 am »
I solved the problem externaly, using bash script. I'm not familiar with fpSelect but I'll look into it.
Thanks
FPC 3.2.2
Lazarus 2.2.4
Debian x86_64, arm

Thaddy

  • Hero Member
  • *****
  • Posts: 14203
  • Probably until I exterminate Putin.
Re: Reading from /dev/usb/lp0 device on Linux
« Reply #4 on: September 28, 2020, 08:38:33 am »
Note the example for fpselect handles time out  :D
Specialize a type, not a var.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Reading from /dev/usb/lp0 device on Linux
« Reply #5 on: September 28, 2020, 08:55:19 am »
I solved the problem externaly, using bash script. I'm not familiar with fpSelect but I'll look into it.
Thanks

fpSelect() is effectively a unix kernel system call. You pass it bitmaps representing handles, and a timeout. You get back which of those handles has shown a sign of activity within the timeout. I don't know how well it integrates with streams.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Thaddy

  • Hero Member
  • *****
  • Posts: 14203
  • Probably until I exterminate Putin.
Re: Reading from /dev/usb/lp0 device on Linux
« Reply #6 on: September 28, 2020, 09:33:59 am »
Yes, you can use fpselect together with the much higher level TFileStream, as well as with Assign/Assignfile Reset/Rewrite to check if a read/write operation will block.
"Bitmaps" is a bit unlucky, although correct: here it is not an image, but a set of bits.  :D
« Last Edit: September 28, 2020, 09:37:01 am by Thaddy »
Specialize a type, not a var.

AlexTP

  • Hero Member
  • *****
  • Posts: 2386
    • UVviewsoft
Re: Reading from /dev/usb/lp0 device on Linux
« Reply #7 on: September 29, 2020, 11:27:59 pm »
Maybe related?
Code: Pascal  [Select][+][-]
  1. procedure TATStrings.LoadFromFile(const AFilename: string);
  2. var
  3.   fs: TFileStream;
  4.   ms: TMemoryStream;
  5. begin
  6.   fs:= TFileStream.Create(AFilename, fmOpenRead or fmShareDenyNone);
  7.   try
  8.     if fs.Size>=0 then
  9.       LoadFromStream(fs)
  10.     else
  11.     begin
  12.       ms:= TMemoryStream.Create;
  13.       try
  14.         _ReadFileToStream(ms, AFilename);
  15.         LoadFromStream(ms);
  16.       finally
  17.         FreeAndNil(ms);
  18.       end;
  19.     end;
  20.   finally
  21.     FreeAndNil(fs);
  22.   end;
  23. end;
  24.  
  25. procedure _ReadFileToStream(AStream: TStream;
  26.   const AFileName: string;
  27.   AMaxSize: integer=20*1024*1024);
  28. const
  29.   BufSize = 4096;
  30. var
  31.   Buf: array[0..BufSize-1] of char;
  32.   fs: TFileStream;
  33.   NSize, NTotalSize: integer;
  34. begin
  35.   fs:= TFileStream.Create(AFileName, fmOpenRead or fmShareDenyNone);
  36.   try
  37.     AStream.Position:= 0;
  38.     NTotalSize:= 0;
  39.     repeat
  40.       NSize:= fs.Read(Buf, BufSize);
  41.       if NSize>0 then
  42.       begin
  43.         AStream.Write(Buf, NSize);
  44.         Inc(NTotalSize, NSize);
  45.         if NTotalSize>=AMaxSize then
  46.           Break;
  47.       end;
  48.     until NSize<BufSize;
  49.   finally
  50.     FreeAndNil(fs);
  51.   end;
  52. end;
  53.  
  54.  

 

TinyPortal © 2005-2018