dnx RTOS 2.2.0 "Eagle"
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
LOOP Driver

Detailed Description

Description

Driver handles virtual loop device. Driver creates special node (file) that can be handled by application (user space) instead of driver (kernel space). Driver can be used as protocol translator or adjust layers e.g. translating access to driver file to special network protocol. There is many driver appliances.

Supported architectures

Details

Meaning of major and minor numbers

The major number determines ID of device. User can create up to 256 driver nodes or up to free operating memory. There is no meaning of minor number.

Numeration restrictions

The major number can be set up to 255. The minor number should be set always to 0.

Driver initialization

To initialize driver the following code can be used:

driver_init("LOOP", 0, 0, "/dev/loop0");
driver_init("LOOP", 1, 0, "/dev/loop1");
driver_init("LOOP", 2, 0, "/dev/loop2");

Driver release

To release driver the following code can be used:

driver_release("LOOP", 0, 0);
driver_release("LOOP", 1, 0);

Driver configuration

Driver does not support any configuration. Driver is ready to use after initialization.

Data write

Data to the loop device can be written as regular file.

Data read

Data from the loop device can be read as regular file.

Other file operations

All file operations are allowed and handling is transparent for client. Only host operations requires special handling.

Host mode

To handle incoming requests from loop device the host application should be started. Application is responsible for handling entire traffic from and to loop node. If request is not handled then client application is waiting for operation to be done.

Registering host application

When host application is registered then is not possible to register additional host application. Only one host can handle loop device. Application registration example:

#include <stdio.h>
#include <sys/ioctl.h>
// ...
const char *loop = "/dev/loop0";
// ...
// opening loop device file
FILE *loop_dev = fopen(loop, "r+");
if (!loop_dev) {
perror(loop);
}
// ...
// registering this application as host
if (ioctl(fileno(loop_dev), IOCTL_LOOP__HOST_OPEN) != 0) {
perror(loop);
fclose(loop_dev);
}
// at this point the loop device is handling by this application
// ...

Unregistering host application

Only host application can unregister loop device. There is no possibility to unregister loop device by other application. Unregister example code:

#include <stdio.h>
#include <sys/ioctl.h>
// ...
const char *loop = "/dev/loop0";
// ...
FILE *loop_dev; // already registered device
// ...
// unregistering this application
if (ioctl(fileno(loop_dev), IOCTL_LOOP__HOST_CLOSE) != 0) {
perror(loop);
fclose(loop_dev);
}
// at this point loop device is not handled by this application
// ...

Handling device requests

All incoming requests are generated by client applications accessing to the loop device. All requests should be handled by host application. In this case host application should check incoming request and then perform required action. Example code:

#include <stdio.h>
#include <sys/ioctl.h>
#include <stdbool.h>
// ...
const char *loop = "/dev/loop0";
// ...
FILE *loop_dev; // already registered device
// ...
while (true) {
LOOP_request_t client_req;
if (ioctl(fileno(loop_dev), IOCTL_LOOP__HOST_WAIT_FOR_REQUEST, &client_req) != 0) {
perror(loop);
continue;
}
switch (client_req.cmd) {
default:
break;
// ...
break;
// ...
break;
// ...
break;
// ...
break;
// ...
break;
}
}
// ...

Handling Client to Host request

This request is used when client application is sending data block to host application. The host application can pass this data forward e.g. by using network protocol or can redirect to other device, or even can handle by itself. Example code of handling Client to Host request:

#include <stdio.h>
#include <sys/ioctl.h>
#include <stdbool.h>
#include <dnx/misc.h>
#include <errno.h>
// ...
const char *loop = "/dev/loop0";
// ...
FILE *loop_dev; // already registered device
uint8_t buffer[64];
// ...
void client2host_transaction(LOOP_request_t *rq)
{
size_t rd = rq.arg.rw.size; // block size
// The file position (rq.arg.rw.seek) can be used as well
while (rd) {
size_t part = min(rd, sizeof(buffer));
// object used to transfer data from client
buf.data = buffer;
buf.size = part;
buf.err = ESUCC;
if (s == 0) {
// buffer is already filled, host can utilize buffer
// ...
rd -= part;
} else {
perror(loop);
break;
}
}
}
// ...

Handling Host to Client request

This request is used when host application is sending data block to client application. Example code of handling Host to Client request:

#include <stdio.h>
#include <sys/ioctl.h>
#include <stdbool.h>
#include <dnx/misc.h>
#include <errno.h>
// ...
const char *loop = "/dev/loop0";
// ...
FILE *loop_dev; // already registered device
uint8_t buffer[64];
// ...
void host2client_transaction(LOOP_request_t *rq)
{
size_t wr = global->client_req.arg.rw.size;
// The file position (rq.arg.rw.seek) can be used as well
while (wr) {
// host should fill buffer
// ...
size_t n = ...;
buf.data = buffer;
buf.size = n;
buf.err = ESUCC;
if (s != 0) {
break;
} else {
wr -= n;
}
}
// if host has not more bytes then can finish transaction
if (wr) {
buf.data = NULL;
buf.size = 0;
buf.err = errno;
}
}
// ...

Handling ioctl request

This request is used when client use ioctl() function. When ioctl() request is specified for other device (not for loop driver) then is not necessary to use IOCTL_LOOP__CLIENT_REQUEST() macro. Only loop driver specified ioctl() request should be send by using mentioned macro. Example code of handling ioctl request:

#include <stdio.h>
#include <sys/ioctl.h>
#include <stdbool.h>
#include <dnx/misc.h>
#include <errno.h>
// ...
const char *loop = "/dev/loop0";
// ...
FILE *loop_dev; // already registered device
uint8_t buffer[64];
// ...
void ioctl_request(LOOP_request_t *rq)
{
// handling request
switch (rq.ioctl.request) {
case ...:
// ...
// The rq.ioctl.arg can be used as well
ioctl_resp.err = ESUCC;
break;
}
if (ioctl(fileno(loop_dev), IOCTL_LOOP__HOST_SET_IOCTL_STATUS, &ioctl_resp) != 0) {
perror(loop);
}
}
// ...

Handling device statistics request

The client program or operating system can check some device statistics. In this the host application should handle statistics request. Example code:

#include <stdio.h>
#include <sys/ioctl.h>
#include <stdbool.h>
#include <dnx/misc.h>
#include <errno.h>
// ...
const char *loop = "/dev/loop0";
// ...
FILE *loop_dev; // already registered device
uint8_t buffer[64];
// ...
void stat_request(LOOP_request_t *rq)
{
stat_resp.size = 100; // example size
stat_resp.err = ESUCC; // operation status
if (ioctl(fileno(loop_dev), IOCTL_LOOP__HOST_SET_DEVICE_STATS, &stat_resp) != 0) {
perror(loop);
}
}
// ...

Handling flush request

There are situations that output buffer should be flushed to e.g. solid state disc. In this case the client application or operating system can send flush request. Example code of handling flush request:

#include <stdio.h>
#include <sys/ioctl.h>
#include <stdbool.h>
#include <dnx/misc.h>
#include <errno.h>
// ...
const char *loop = "/dev/loop0";
// ...
FILE *loop_dev; // already registered device
uint8_t buffer[64];
// ...
void flush_request(LOOP_request_t *rq)
{
// flush operation
// ...
int err = ESUCC;
if (ioctl(fileno(loop_dev), IOCTL_LOOP__HOST_FLUSH_DONE, &err) != 0) {
perror(loop);
}
}
// ...

Data Structures

struct  LOOP_buffer_t
 
struct  LOOP_ioctl_response_t
 
struct  LOOP_stat_response_t
 
struct  LOOP_request_t
 
union  LOOP_request_t.arg
 
struct  LOOP_request_t.arg.rw
 
struct  LOOP_request_t.arg.ioctl
 

Macros

#define IOCTL_LOOP__HOST_OPEN   _IO(LOOP, 0x00)
 Host request. Set this program as Host. More...
 
#define IOCTL_LOOP__HOST_CLOSE   _IO(LOOP, 0x01)
 Host request. Disconnect this program as host function. More...
 
#define IOCTL_LOOP__HOST_WAIT_FOR_REQUEST   _IOR(LOOP, 0x02, LOOP_request_t*)
 Host request. Wait for request from Client. More...
 
#define IOCTL_LOOP__HOST_READ_DATA_FROM_CLIENT   _IOR(LOOP, 0x03, LOOP_buffer_t*)
 Host request. Read data from buffers shared by the Client. More...
 
#define IOCTL_LOOP__HOST_WRITE_DATA_TO_CLIENT   _IOW(LOOP, 0x04, LOOP_buffer_t*)
 Host request. Write data to the client. More...
 
#define IOCTL_LOOP__HOST_SET_IOCTL_STATUS   _IOW(LOOP, 0x05, LOOP_ioctl_response_t*)
 Host request. Response to the captured ioctl request. More...
 
#define IOCTL_LOOP__HOST_SET_DEVICE_STATS   _IOW(LOOP, 0x06, LOOP_ioctl_response_t*)
 Host request. Response to the captured stat request. More...
 
#define IOCTL_LOOP__HOST_FLUSH_DONE   _IOW(LOOP, 0x07, int*)
 Host request. Response to the captured flush request. More...
 
#define IOCTL_LOOP__CLIENT_REQUEST(n)   _IOWR(LOOP, 0x08 + n, void*)
 Client request. General purpose RAW request. Depends on host protocol. More...
 

Enumerations

enum  LOOP_cmd_t
 

Data Structure Documentation

struct LOOP_buffer_t

Type represent buffer descriptor for I/O operations.

Data Fields
u8_t * data

Write/read Host buffer address.

int err

Errno value if error occurred (if no error must be set to ESUCC).

size_t size

Number of bytes to write/read.

struct LOOP_ioctl_response_t

Type represent the response host->client for the ioctl request coming from client.

Data Fields
int err

Errno value if error occurred (if no error must be set to ESUCC).

struct LOOP_stat_response_t

Type represent the response host->client for the stat() request coming from client.

Data Fields
int err

Errno value if error occurred (if no error must be set to ESUCC).

u64_t size

Device capacity/file size.

struct LOOP_request_t

Type represent the request.

Data Fields
union LOOP_request_t arg

Command's arguments.

LOOP_cmd_t cmd

Requested action (command from Client).

union LOOP_request_t.arg
Data Fields
arg ioctl

Ioctl argument group.

arg rw

Read/write transmission arguments group.

struct LOOP_request_t.arg.rw
Data Fields
fpos_t seek

Position in the device's file.

size_t size

Requested size of read/write operation.

struct LOOP_request_t.arg.ioctl
Data Fields
void * arg

Ioctl's request argument.

int request

Ioctl's request number.

Macro Definition Documentation

#define IOCTL_LOOP__CLIENT_REQUEST (   n)    _IOWR(LOOP, 0x08 + n, void*)

By this request Client can send request from another device type. In this case is not required to use IOCTL_LOOP__CLIENT_REQUEST() macro.

Parameters
nrequest number (macro's argument)
Returns
Depends on host program protocol.
#define IOCTL_LOOP__HOST_CLOSE   _IO(LOOP, 0x01)

After this operation any program can be a host if request OPEN function.

Returns
On success 0 is returned, otherwise -1.
#define IOCTL_LOOP__HOST_FLUSH_DONE   _IOW(LOOP, 0x07, int*)
Parameters
[WR]int* errno value
Returns
On success 0 is returned, otherwise -1.
#define IOCTL_LOOP__HOST_OPEN   _IO(LOOP, 0x00)

After this operation this program has only possibility to gets requests from Client program.

Returns
On success 0 is returned, otherwise -1.
#define IOCTL_LOOP__HOST_READ_DATA_FROM_CLIENT   _IOR(LOOP, 0x03, LOOP_buffer_t*)

When host send all bytes or send 0-length buffer then read operation is finished. If operation is not finished, then timeout was generated. If host wants to finish operation earlier the ZLB (Zero-Length Buffer) should be send (buffer size = 0).

Parameters
[RD]LOOP_buffer_t* host buffer descriptor
Returns
On success 0 is returned, otherwise -1.
#define IOCTL_LOOP__HOST_SET_DEVICE_STATS   _IOW(LOOP, 0x06, LOOP_ioctl_response_t*)
Parameters
[WR]LOOP_stat_response_t* device statistics response
Returns
On success 0 is returned, otherwise -1.
#define IOCTL_LOOP__HOST_SET_IOCTL_STATUS   _IOW(LOOP, 0x05, LOOP_ioctl_response_t*)

This request is send as response when Client requested IOCTL action in the command capture request.

Parameters
[WR]LOOP_ioctl_response_t* ioctl response data
Returns
On success 0 is returned, otherwise -1.
#define IOCTL_LOOP__HOST_WAIT_FOR_REQUEST   _IOR(LOOP, 0x02, LOOP_request_t*)

Client request and arguments are set in the loop_client_rq_t-type variable. Host application should read this variable and perform requested actions.

Parameters
[RD]LOOP_request_t* request details
Returns
On success 0 is returned, otherwise -1.
#define IOCTL_LOOP__HOST_WRITE_DATA_TO_CLIENT   _IOW(LOOP, 0x04, LOOP_buffer_t*)

Write operation is finished and Client is resumed when buffer size is set to 0 (this means that Host written all data to the buffer) or all bytes was written. Write operation can be done by sending small buffers (is not required to send entire requested buffer in one part).

Parameters
[WR]LOOP_buffer_t* host buffer descriptor
Returns
On success 0 is returned, otherwise -1.

Enumeration Type Documentation

enum LOOP_cmd_t

Type represent the command of loop device.

Enumerator
LOOP_CMD__IDLE 

Idle command, no action.

LOOP_CMD__TRANSMISSION_CLIENT2HOST 

Transmission request client to host (rw arguments are valid).

LOOP_CMD__TRANSMISSION_HOST2CLIENT 

Transmission request host to client (rw arguments are valid).

LOOP_CMD__IOCTL_REQUEST 

Ioctl operation request (ioctl arguments are valid).

LOOP_CMD__DEVICE_STAT 

Request to response by device's statistics.

LOOP_CMD__FLUSH_BUFFERS 

Request to flush device buffers.