flinklib
flinklib: flink C library for Linux
lowlevel.c
Go to the documentation of this file.
1 /*******************************************************************
2  * _________ _____ _____ ____ _____ ___ ____ *
3  * |_ ___ | |_ _| |_ _| |_ \|_ _| |_ ||_ _| *
4  * | |_ \_| | | | | | \ | | | |_/ / *
5  * | _| | | _ | | | |\ \| | | __'. *
6  * _| |_ _| |__/ | _| |_ _| |_\ |_ _| | \ \_ *
7  * |_____| |________| |_____| |_____|\____| |____||____| *
8  * *
9  *******************************************************************
10  * *
11  * fLink userspace library, low level operations *
12  * *
13  *******************************************************************/
14 
26 #include "flinklib.h"
27 #include "flinkioctl.h"
28 #include "types.h"
29 #include "error.h"
30 #include "log.h"
31 #include "valid.h"
32 
33 #include <sys/ioctl.h>
34 #include <unistd.h>
35 
36 
44 int flink_ioctl(flink_dev* dev, int cmd, void* arg) {
45  int ret;
46 
47  dbg_print("flink_ioctl '0x%x'\n", cmd);
48 
49  if(!validate_flink_dev(dev)) {
51  return EXIT_ERROR;
52  }
53 
54  ret = ioctl(dev->fd, cmd, arg);
55  if(ret < 0) {
56  libc_error();
57  }
58 
59  return ret;
60 }
61 
62 
71 ssize_t flink_read(flink_subdev* subdev, uint32_t offset, uint8_t size, void* rdata) {
72  ssize_t read_size = 0;
73  ioctl_container_t ioctl_arg;
74  ioctl_arg.subdevice = subdev->id;
75  ioctl_arg.offset = offset;
76  ioctl_arg.size = size;
77  ioctl_arg.data = rdata;
78 
79  // Check data pointer
80  if(rdata == NULL) {
82  return EXIT_ERROR;
83  }
84 
85  // Check flink subdevice structure
86  if(!validate_flink_subdev(subdev)) {
88  return EXIT_ERROR;
89  }
90 
91  // read data from device
92  read_size = flink_ioctl(subdev->parent, SELECT_AND_READ, &ioctl_arg);
93  if(read_size == -1) {
94  libc_error();
95  return EXIT_ERROR;
96  }
97 
98  return read_size;
99 }
100 
101 
110 ssize_t flink_write(flink_subdev* subdev, uint32_t offset, uint8_t size, void* wdata) {
111  ssize_t write_size = 0;
112  ioctl_container_t ioctl_arg;
113  ioctl_arg.subdevice = subdev->id;
114  ioctl_arg.offset = offset;
115  ioctl_arg.size = size;
116  ioctl_arg.data = wdata;
117 
118  // Check data pointer
119  if(wdata == NULL) {
121  return EXIT_ERROR;
122  }
123 
124  // Check flink subdevice structure
125  if(!validate_flink_subdev(subdev)) {
127  return EXIT_ERROR;
128  }
129 
130  // write data to device
131  write_size = flink_ioctl(subdev->parent, SELECT_AND_WRITE, &ioctl_arg);
132  if(write_size == -1) {
133  libc_error();
134  return EXIT_ERROR;
135  }
136 
137  return write_size;
138 }
139 
140 
149 int flink_read_bit(flink_subdev* subdev, uint32_t offset, uint8_t bit, void* rdata) {
150  ioctl_bit_container_t ioctl_arg;
151  ioctl_arg.offset = offset;
152  ioctl_arg.bit = bit;
153  ioctl_arg.subdevice = subdev->id;
154 
155  // Check data pointer
156  if(rdata == NULL) {
158  return EXIT_ERROR;
159  }
160 
161  // Check flink subdevice structure
162  if(!validate_flink_subdev(subdev)) {
164  return EXIT_ERROR;
165  }
166 
167  // select subdevice and read data
168  if(flink_ioctl(subdev->parent, SELECT_AND_READ_BIT, &ioctl_arg) < 0) {
169  libc_error();
170  return EXIT_ERROR;
171  }
172 
173  *((uint8_t*)rdata) = ioctl_arg.value;
174 
175  return EXIT_SUCCESS;
176 }
177 
178 
187 int flink_write_bit(flink_subdev* subdev, uint32_t offset, uint8_t bit, void* wdata) {
188  ioctl_bit_container_t ioctl_arg;
189  ioctl_arg.offset = offset;
190  ioctl_arg.bit = bit;
191  ioctl_arg.value = *((uint8_t*)wdata);
192  ioctl_arg.subdevice = subdev->id;
193 
194  // Check data pointer
195  if(wdata == NULL) {
197  return EXIT_ERROR;
198  }
199 
200  // Check flink subdevice structure
201  if(!validate_flink_subdev(subdev)) {
203  return EXIT_ERROR;
204  }
205 
206  // select subdevice and write data
207  if(flink_ioctl(subdev->parent, SELECT_AND_WRITE_BIT, &ioctl_arg) < 0) {
208  libc_error();
209  return EXIT_ERROR;
210  }
211 
212  return EXIT_SUCCESS;
213 }
Data structures for flink devices and subdevices.
uint8_t bit
Offset of byte containing the single bit, taken from subdevice base address.
Definition: flinkioctl.h:29
ssize_t flink_write(flink_subdev *subdev, uint32_t offset, uint8_t size, void *wdata)
Write to a flink subdevice.
Definition: lowlevel.c:110
void * data
size of data
Definition: flinkioctl.h:38
#define FLINK_ENULLPTR
Definition: error.h:32
uint32_t offset
subdevice to read from / write to
Definition: flinkioctl.h:36
#define FLINK_EINVALDEV
Definition: error.h:29
uint8_t value
Bit number in byte.
Definition: flinkioctl.h:30
#define EXIT_ERROR
Definition: flinklib.h:129
uint8_t subdevice
Value of the bit.
Definition: flinkioctl.h:31
Error handling.
uint8_t size
offset to base address of subdevice
Definition: flinkioctl.h:37
flink userspace library, ioctl definitions.
#define EXIT_SUCCESS
Definition: flinklib.h:128
int flink_read_bit(flink_subdev *subdev, uint32_t offset, uint8_t bit, void *rdata)
Read a single bit from a flink subdevice.
Definition: lowlevel.c:149
int flink_ioctl(flink_dev *dev, int cmd, void *arg)
IOCTL operation for a flink device.
Definition: lowlevel.c:44
int validate_flink_subdev(flink_subdev *subdev)
Checks if flink subdevice belongs to the device.
Definition: valid.c:40
Contains validation functions for flink.
flink_dev * dev
void flink_error(int e)
Definition: error.c:64
ssize_t flink_read(flink_subdev *subdev, uint32_t offset, uint8_t size, void *rdata)
Read from a flink subdevice.
Definition: lowlevel.c:71
int validate_flink_dev(flink_dev *dev)
Checks if flink device was opened.
Definition: valid.c:28
int flink_write_bit(flink_subdev *subdev, uint32_t offset, uint8_t bit, void *wdata)
Write a single bit to a flink subdevice.
Definition: lowlevel.c:187
void libc_error(void)
Definition: error.c:56
Debug utilities.
#define dbg_print(fmt,...)
Definition: log.h:29