From: ansofive on
Hi,

I've broken out my old Mindstorms kit and I'm working on a simple
package to send commands to the brick from my workstation. You send
data to the brick over a USB device so I open the device file (/dev/
usb/legousbtower0) and write my packet - Works fine, lasts a long
time. Here's what I have so far:

(defun send-message (message &key (port *port*))
"Send a list of bytes to the brick and wait for the reply."
(with-open-file (stream port
:direction :io
:if-does-not-exist :create
:if-exists :overwrite
:element-type '(unsigned-byte 8))
(write-sequence (mk-packet message) stream)
#+ignore(read-packet stream)))

(defun read-packet (stream)
(let ((buffer (make-array 8 :element-type '(unsigned-byte 8))))
(read-sequence buffer stream)
buffer))

My problem is in the read-packet form - I would like to read any reply
that is sent by the brick in response to the packet. I've tried a
couple of different ways to read from the device - looping until read-
byte fails and read-sequence both seem to simply wait forever. I am
assuming that they seem to hang because the "file" is a character
device and not a file-system file - there is no end-of-file condition
to tell the read-stuff functions that there is no more data. It could
also be that the USB receive queue is empty by the time the read-
sequence is called and the read is simply waiting for the next byte.

How do I read the response from the USB device? Eventually I would
like to be able to read much larger chunks of data from the brick, the
maximum would be 32KB as that is the size of the RAM on the device.
Any clues are appreciated.

Thanks,

Dennis

PS. My environment is SBCL on 64-bit Linux (Ubuntu 10.04).
From: Pascal J. Bourguignon on
"ansofive(a)gmail.com" <ansofive(a)gmail.com> writes:

> Hi,
>
> I've broken out my old Mindstorms kit and I'm working on a simple
> package to send commands to the brick from my workstation. You send
> data to the brick over a USB device so I open the device file (/dev/
> usb/legousbtower0) and write my packet - Works fine, lasts a long
> time. Here's what I have so far:
>
> (defun send-message (message &key (port *port*))
> "Send a list of bytes to the brick and wait for the reply."
> (with-open-file (stream port
> :direction :io
> :if-does-not-exist :create
> :if-exists :overwrite
> :element-type '(unsigned-byte 8))
> (write-sequence (mk-packet message) stream)
> #+ignore(read-packet stream)))
>
> (defun read-packet (stream)
> (let ((buffer (make-array 8 :element-type '(unsigned-byte 8))))
> (read-sequence buffer stream)
> buffer))
>
> My problem is in the read-packet form - I would like to read any reply
> that is sent by the brick in response to the packet. I've tried a
> couple of different ways to read from the device - looping until read-
> byte fails and read-sequence both seem to simply wait forever. I am
> assuming that they seem to hang because the "file" is a character
> device and not a file-system file - there is no end-of-file condition
> to tell the read-stuff functions that there is no more data. It could
> also be that the USB receive queue is empty by the time the read-
> sequence is called and the read is simply waiting for the next byte.
>
> How do I read the response from the USB device? Eventually I would
> like to be able to read much larger chunks of data from the brick, the
> maximum would be 32KB as that is the size of the RAM on the device.
> Any clues are appreciated.

You ay use CL:LISTEN to learn whether a byte is available or not.

Using CL:LISTEN and CL:READ-BYTE, you should be able to avoid blocking
in a portable way.

--
__Pascal Bourguignon__
http://www.informatimago.com
From: Dennis Dunn on
Hello,

On 7/15/2010 12:18 PM, Pascal J. Bourguignon wrote:
> You ay use CL:LISTEN to learn whether a byte is available or not.
>
> Using CL:LISTEN and CL:READ-BYTE, you should be able to avoid blocking
> in a portable way.
>

Thanks for the idea. It looks like there is nothing to be read from the
USB device because the following code returns an empty vector.

(defun read-packet (stream)
(let (buffer)
(loop while (listen stream) do
(push (read-byte stream) buffer))
(make-array (length buffer) :element-type '(unsigned-byte 8)
:initial-contents (reverse buffer))))

The sending bit is working great - it's just reading the reply that is
the problem. My next step will be to get the brick to send a stream of
messages and then try to read them with read-packet on a stream that's
been opened for :input, not :io.

Thanks again.

Dennis

From: ansofive on
Hi,

I've been playing around with this and I've discovered that listen
seems to only work with character streams. I've only tried it on
clisp at this point but it wouldn't suprise me if it was the same on
sbcl. The HyperSpec says "Returns true if there is a character
immediately available ... listen is intended to be used when input-
stream obtains characters from an interactive device such as a
keyboard. " which seems to suggest that listen wants a character
stream.

Is there character encoding that allows be to read 8-bit characters?
Hmmmm..... Seems to me I remember something from Practical Common
Lisp......

Thanks,

Dennis
From: Pascal J. Bourguignon on
"ansofive(a)gmail.com" <ansofive(a)gmail.com> writes:

> Hi,
>
> I've been playing around with this and I've discovered that listen
> seems to only work with character streams. I've only tried it on
> clisp at this point but it wouldn't suprise me if it was the same on
> sbcl. The HyperSpec says "Returns true if there is a character
> immediately available ... listen is intended to be used when input-
> stream obtains characters from an interactive device such as a
> keyboard. " which seems to suggest that listen wants a character
> stream.

Oops, I forgot that.


> Is there character encoding that allows be to read 8-bit characters?
> Hmmmm..... Seems to me I remember something from Practical Common
> Lisp......

Yes, you can use charset:iso-8859-1 or any of the other iso-8859-* charsets.


--
__Pascal Bourguignon__ http://www.informatimago.com/