Streams¶
Streams are the abstractions for exchanging data with anything: a local or distant file, a device through serial or USB communications, local memory (usually for simulation), etc.
The stream object is usable both by the library and the user. The library defines some useful platform-agnostic streams it uses itself, such as the checksum stream (which calculates the checksum as the file content is read), and some platform-specific streams for platforms defining a macro.
-
tio_stream_t
¶ An object representing a stream.
A stream as defined in libtio is a handle representing an I/O device or file, which can have one of these types:
-
TIO_TYPE_GENERIC
¶ The stream is a basic I/O stream (as
FILE
) on which you can read, write and sometimes seek. It can be used for files.
-
TIO_TYPE_SERIAL
¶ The stream is an I/O stream on a serial line on which you can read, write and set the attributes (settings) and timeouts.
-
TIO_TYPE_USB
¶ The stream is a USB device which you can get and USB packets on.
-
TIO_TYPE_SCSI
¶ The stream is an SCSI device to which you can send SCSI requests to.
Streams can be defined on top of each other with the concept of “parent streams”: for example, a USB storage key will use SCSI over USB, by the use of an SCSI stream defined onto a USB stream. This allows you to send and receive USB packets as well as SCSI requests on the SCSI stream, which can be useful if the device supports some custom USB interactions.
This document describes how to use and make a libtio stream. Notice that
for the examples in this document, you shall include <libtio.h>
, or
the stream-specific header, <libtio/stream.h>
.
Opening and closing a stream¶
There are two ways to open a stream:
with a specialized function, such as
tio_open_unix_fd()
for POSIX;with a platform-agnostic function, such as
tio_open_usb()
;with the core function,
tio_open()
, which you will use when you will want to define your own streams.
All of the stream opening functions shall take a reference to the stream pointer you’ll use as the stream handle as the first parameter, and return the libtio error code that occurred.
Once you are done with the stream, you shall close it, so that all of the
allocated resources can be free’d properly. In order to do this,
you can simply use tio_close()
.
int tio_open_any_stream(tio_stream_t **stream, ...);
int tio_close(tio_stream_t *stream);
So here’s a simple example using the tio_open_memory()
function
(which makes a stream out of memory), for opening a stream and directly
closing it:
#include <libtio.h>
void do_something()
{
int err;
tio_stream_t *stream = NULL;
char zone[6];
err = tio_open_memory(&stream, zone, 6);
if (err) {
/* an error has occured! */
return ;
}
/* do something here, if an error occurs, make sure to
close the stream anyway, or use the 'fail' label here */
fail:
err = tio_close(stream);
/* you can check the error if you want, but the stream will always
be closed at this point, more or less properly */
}
Getting the stream properties¶
You can use the following functions to get properties from any stream:
-
int
tio_get_type
(tio_stream_t *stream)¶ Returns the stream type.
Returns the stream cookie (hoping that you have the structure to it, because the library probably doesn’t).
-
int
tio_get_lasterr
(tio_stream_t *stream)¶ Returns the last error that has occurred with the stream. Prefer getting the error directly for simple operation failures.
-
int
tio_get_parent
(tio_stream_t *stream, tio_stream_t **parentp)¶ Get the parent stream pointer.
And in order to check if you can issue some operations to a stream, you can use the following functions:
-
int
tio_is_readable
(tio_stream_t *stream)¶ Check if the stream is readable.
-
int
tio_is_writable
(tio_stream_t *stream)¶ Check if the stream is writable.
-
int
tio_is_seekable
(tio_stream_t *stream)¶ Check if the stream is seekable.
Reading and writing to a stream¶
These functions both work for generic and serial streams.
-
int
tio_set_timeouts
(tio_stream_t *stream, tio_timeouts_t const *read_timeouts, tio_timeouts_t const *write_timeouts)¶ Set the stream timeouts for read and write operations.
-
int
tio_read
(tio_stream_t *stream, void *dest, size_t count)¶ Read exactly
count
bytes from the stream intodest
, while complying with the stream timeouts.
-
int
tio_read_tm
(tio_stream_t *stream, void *dest, size_t count, tio_timeouts_t const *tm)¶ Read exactly
count
bytes from the stream intodest
, while complying with the timeouts defined intm
.
-
int
tio_write
(tio_stream_t *stream, void const *data, size_t count)¶ Write exactly
count
bytes to the stream fromdata
, while complying with the stream timeouts.
-
int
tio_write_tm
(tio_stream_t *stream, void *dest, size_t count, tio_timeouts_t const *tm)¶ Write exactly
count
bytes to the stream fromdata
, while complying with the timeouts defined intm
.
-
int
tio_write_char
(tio_stream_t *stream, int char)¶ Write a byte to the stream.
-
int
tio_skip
(tio_stream_t *stream, tio_off_t size)¶ Skip exactly
size
bytes on the stream. For seekable generic streams, it is actually an equivalent to the following call:tio_seek(stream, TIO_SEEK_CUR, size);
Using a generic stream¶
The following functions ought to be used with generic streams:
-
int
tio_seek
(tio_stream_t *stream, tio_off_t offset, tio_whence_t whence)¶ Seek to a position in the stream, depending on
whence
:TIO_SEEK_SET
Seek to the stream start plus
offset
.TIO_SEEK_CUR
Seek to the stream current cursor position plus
offset
.TIO_SEEK_END
Seek to the stream end minus
offset
.
-
int
tio_get_size
(tio_stream_t *stream, tio_off_t *size)¶ Find out the stream size (using
tio_seek()
behind as a fallback).
Using a serial stream¶
Serial streams have attributes (or settings), represented using the following type:
-
tio_serial_attrs
¶ The link settings of a serial stream.
-
unsigned int
tio_serial_attrs_flags
¶ The various link settings flags (todo).
-
unsigned long
tio_serial_speed
¶ The speed in bauds of the link.
-
unsigned char
tio_serial_attrs_cc
¶ The special characters for the link.
-
unsigned int
The following functions ought to be used with serial streams:
-
int
tio_make_serial_attrs
(tio_serial_attrs_t *attrs, char const *raw)¶ Initialize serial attributes, possibly from a string which can be used for command-line interfaces (e.g.
19200N2
).
-
int
tio_get_serial_attrs
(tio_stream_t *stream, unsigned int flags, tio_serial_attrs_t *attrs)¶ Get the current serial attributes from a stream.
-
int
tio_set_serial_attrs
(tio_stream_t *stream, unsigned int flags, tio_serial_attrs_t const *attrs)¶ Set the current serial attributes on the stream.
Using a USB stream¶
The following functions ought to be used with USB streams:
-
int
tio_usb_send_bulk
(tio_stream_t *stream, unsigned char const *data, size_t size, unsigned int timeout)¶ Send data using USB bulk packets.
-
int
tio_usb_recv_bulk
(tio_stream_t *stream, unsigned char *buf, size_t size, unsigned int timeout)¶ Receive data from the next USB bulk packet.
Using an SCSI stream¶
The following functions ought to be used with serial streams:
-
int
tio_scsi_request
(tio_stream_t *stream, tio_scsi_request_t *request)¶ Send a SCSI request and get answers.
Which mainly uses the following structure:
-
tio_scsi_request_t
¶ The request input and output structure.
-
void *
tio_scsi_request_cmd
¶ The command (as a 8, 12 or 16 bytes data block).
-
size_t
tio_scsi_request_cmd_len
¶ The length of the command data pointed above.
-
int
tio_scsi_request_direction
¶ The data direction, as one of the
TIO_SCSI_DIREC_*
constants.
-
void *
tio_scsi_request_data
¶ The data to transfer or a pointer to the buffer to fill, depending on the direction given above.
-
size_t
tio_scsi_request_data_len
¶ The length of the data or buffer pointed above.
-
int
tio_scsi_request_status
¶ The status byte returned by the device.
-
void *