comp.lang.ada
 help / color / mirror / Atom feed
* Read/write access to Unix character devices
@ 2020-12-21  4:59 philip...@gmail.com
  2020-12-22  1:23 ` Randy Brukardt
  2020-12-28 13:26 ` Björn Lundin
  0 siblings, 2 replies; 3+ messages in thread
From: philip...@gmail.com @ 2020-12-21  4:59 UTC (permalink / raw)


Lately I have been working with Unix (really Linux, FreeBSD, and OpenBSD) character devices (these happen to be USB raw HID devices, but the problem is more general than that).  The way these work is that each hardware device has a character device node file in /dev/, like /dev/hidraw1.  You open the file for both read and write access.  Then you can send a command to the device by writing a binary blob and get a response by subsequently reading a binary blob.  For what I am doing, it is important not to block on reads forever if there is not response forthcoming, so I need at least read timeouts.

So far, I have been binding the C library functions open(), close(), read(), write(), and poll() with pragma Import.  That works, but I have wondered if there is some way of accomplishing the same thing more portably.  The packages GNAT.Sockets and GNAT.Serial_Communicatons can be viewed as special case solutions, but I would like a general solution.

What I would really like is Ada.Sequential_IO with InOut_File and a timeout mechanism, perhaps like the select() wrapper in GNAT.Sockets.

So far I haven't found anything in the Ada. or GNAT. that supports InOut_File semantics (other than Direct_IO) let alone timeouts.  Does anybody have any suggestions?

Phil

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Read/write access to Unix character devices
  2020-12-21  4:59 Read/write access to Unix character devices philip...@gmail.com
@ 2020-12-22  1:23 ` Randy Brukardt
  2020-12-28 13:26 ` Björn Lundin
  1 sibling, 0 replies; 3+ messages in thread
From: Randy Brukardt @ 2020-12-22  1:23 UTC (permalink / raw)


I would use Stream_IO for this, but you'd need help from your implementer to 
get timeouts/nonblocking I/O. If they have them, they'd be some sort of Form 
parameter (that's what the typically ignored Form parameter is for).

Stream_IO is a lot more flexible that Sequential_IO and Direct_IO. (Some 
implementations implement those older Ada 83 packages in terms of 
Stream_IO.)

                          Randy.

"philip...@gmail.com" <philip.munts@gmail.com> wrote in message 
news:6ece98b8-a82e-40e7-9a0e-37b40a175fb0n@googlegroups.com...
Lately I have been working with Unix (really Linux, FreeBSD, and OpenBSD) 
character devices (these happen to be USB raw HID devices, but the problem 
is more general than that).  The way these work is that each hardware device 
has a character device node file in /dev/, like /dev/hidraw1.  You open the 
file for both read and write access.  Then you can send a command to the 
device by writing a binary blob and get a response by subsequently reading a 
binary blob.  For what I am doing, it is important not to block on reads 
forever if there is not response forthcoming, so I need at least read 
timeouts.

So far, I have been binding the C library functions open(), close(), read(), 
write(), and poll() with pragma Import.  That works, but I have wondered if 
there is some way of accomplishing the same thing more portably.  The 
packages GNAT.Sockets and GNAT.Serial_Communicatons can be viewed as special 
case solutions, but I would like a general solution.

What I would really like is Ada.Sequential_IO with InOut_File and a timeout 
mechanism, perhaps like the select() wrapper in GNAT.Sockets.

So far I haven't found anything in the Ada. or GNAT. that supports 
InOut_File semantics (other than Direct_IO) let alone timeouts.  Does 
anybody have any suggestions?

Phil 


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Read/write access to Unix character devices
  2020-12-21  4:59 Read/write access to Unix character devices philip...@gmail.com
  2020-12-22  1:23 ` Randy Brukardt
@ 2020-12-28 13:26 ` Björn Lundin
  1 sibling, 0 replies; 3+ messages in thread
From: Björn Lundin @ 2020-12-28 13:26 UTC (permalink / raw)


Den 2020-12-21 kl. 05:59, skrev philip...@gmail.com:
> Lately I have been working with Unix (really Linux, FreeBSD, and OpenBSD) character devices (these happen to be USB raw HID devices, but the problem is more general than that).  The way these work is that each hardware device has a character device node file in /dev/, like /dev/hidraw1.  You open the file for both read and write access.  Then you can send a command to the device by writing a binary blob and get a response by subsequently reading a binary blob.  For what I am doing, it is important not to block on reads forever if there is not response forthcoming, so I need at least read timeouts.
> 
> So far, I have been binding the C library functions open(), close(), read(), write(), and poll() with pragma Import.  That works, but I have wondered if there is some way of accomplishing the same thing more portably.  The packages GNAT.Sockets and GNAT.Serial_Communicatons can be viewed as special case solutions, but I would like a general solution.
> 
> What I would really like is Ada.Sequential_IO with InOut_File and a timeout mechanism, perhaps like the select() wrapper in GNAT.Sockets.
> 
> So far I haven't found anything in the Ada. or GNAT. that supports InOut_File semantics (other than Direct_IO) let alone timeouts.  Does anybody have any suggestions?
> 
> Phil
> 


I'm perhaps too late for a useful suggestion, but I use this pattern 
when I pass messages through named pipes between unrelated processes.


The reading process starts a task T1 which reads the pipe blocking.
When data arrives it puts it in a list via a protected object,
then it goes back to read blocking again.


T1:
loop
   read device
   PO.Put(data from device)
   exit when data is special shutdown-message
end loop


The main of the process does a IO.receive which in turn does a 'Get' on 
a protected object where 'get' is an entry of the PO with condition 
list.count > 0

main:
   loop
     IO.Receive(Data, Timeout)
     case Data.id is
       when timeout => DoSomethingElse
       when  reply  => Treat(Data)
       when shutdown => exit
     end case
   end loop;


So - the main hangs on receive until a message arrives.
And with receive, there is an optional timeout, that if > 0, starts a 
new task T2 that is a timer. If no message has arrived within time,
a timeout message is put by T2 into the list, and the T2 dies.

pkg IO
procedure Receive (msg out: some type ; timeout : duration := 0.0) is
   TTP : Timer_Task_Pointer_Type;
   TO  : aliased Duration := Timeout;
begin
  if Timeout > 0.0 then
    TTP := new Timer_Task_Type(TO'Unchecked_access);
    PO.Get(msg); <-- we hang here until msg from device or timeout from T2
    begin
      TTP.Stop;
      loop
        exit when TTP.all'Terminated;
        delay 0.0001; --workaround gnat bug
      end loop;
    exception
      when Tasking_Error => null;
    end;
    Free(TTP);
  end if;
end receive;


T2
   task type Timer_Task_Type(Timeout_Time : access Duration) is
     entry Stop;
   end Timer_Task_Type;

   task body Timer_Task_Type is
     Timeout_Message : Message_Type;
   begin
     select
       delay Timeout_Time.all;
       Timeout_Message.Msg.Header.Identity := Time_Out_Identity;
       PO.Put(Timeout_Message);
     or
       accept Stop;
     end select;
   end Timer_Task_Type;

   type Timer_Task_Pointer_Type is access all Timer_Task_Type;

   procedure Free is new 
Unchecked_Deallocation(Timer_Task_Type,Timer_Task_Pointer_Type);




Main is released by this timeout message and can do other things while 
T1 still hangs on the device waiting for data.


To exit the process I post a special exit message that the task puts 
into the list and then exits its task loop, thus dies.

Then the process shuts down when it acts upon the shutdown message.

In your case you may not be able to send such a message to the task, but
that does perhaps not matter. abort the task when shutting down your 
process - if you ever shut it down that is.


-- 
Björn

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-12-28 13:26 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-21  4:59 Read/write access to Unix character devices philip...@gmail.com
2020-12-22  1:23 ` Randy Brukardt
2020-12-28 13:26 ` Björn Lundin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox