felHR85 / UsbSerial

Usb serial controller for Android
MIT License
1.82k stars 599 forks source link

Feature request: Unbuffered write #27

Closed autowp closed 8 years ago

autowp commented 8 years ago

In my application i need unbuffered synchronous write to provide equal spacing between the end of each and start of subsequent transmits. (using ScheduledExecutorService.scheduleWithFixedDelay)

Transmit time can be greater than delay between transmits. Thats means write buffer overflows if used buffered write.

ScheduledExecutorService service = Executors.newScheduledThreadPool(N);
service.scheduleWithFixedDelay(new Runnable() {
  @Override
        public void run() {
            Serial.write(buffer);
        }
}, 0, delay, TimeUnit.MILLISECONDS);

Quick patch to add unbuffered synchrowrite: https://github.com/autowp/UsbSerial/commit/a6ab307909f09f71d30be570902c94f1ed7f8a72

Maybe that needs not only for me and unbuffered interface appears in the library

felHR85 commented 8 years ago

Hi @autowp there are more people with that need. I will try to add a way to choose between sync and async api as soon as possible

autowp commented 8 years ago

I think it is also necessary to read for symmetry.

It's useful for dialog transfers where next submition wait for previous response

felHR85 commented 8 years ago

I've added a synchronous way to write and read in UsbSerial (version 4.1).

public boolean syncOpen();
public int syncWrite(byte[] buffer, int timeout)
public int syncRead(byte[] buffer, int timeout)
public void syncClose();

It would be nice if you could give it a try! @autowp

autowp commented 8 years ago

In my apps it works, but ...

syncRead works in poll mode. Non blocking. I think that is becase FTDI 2 bytes response. Hmm

felHR85 commented 8 years ago

In the FTDI devices I am just ignoring the 2 byte header and in case I've only got those two bytes I return 0 bytes read. It is a blocking call

autowp commented 8 years ago

Nope, i think it is not blocking.

while (true) {
    mSerial.syncRead(buffer, 60000);
    System.out.println("timeout");
}

That prints "timeout" continously without 60s delay on empty input.

felHR85 commented 8 years ago

Ok! you set the timer to 60 seconds but in the FTDI devices just return every 40 ms because the modem status is sent continuously (returning 0 bytes read). I have to ignore those bytes till the timeout is over

autowp commented 8 years ago

Yes. That means the read is not blocking. I think its no way to fix that with FTDI, but interface can be little better if not only ignore 2 bytes, but wait up to timeout for payload bytes.

Quick fix: https://github.com/felHR85/UsbSerial/pull/30

felHR85 commented 8 years ago

I was trying to fix it right now! Basically the same as you did so I will check it out and I will merge it

felHR85 commented 8 years ago

Thank you very much for your help @autowp Pull request accepted