flinklib
flinklib: flink C library for Linux
base.c
Go to the documentation of this file.
1 /*******************************************************************
2  * _________ _____ _____ ____ _____ ___ ____ *
3  * |_ ___ | |_ _| |_ _| |_ \|_ _| |_ ||_ _| *
4  * | |_ \_| | | | | | \ | | | |_/ / *
5  * | _| | | _ | | | |\ \| | | __'. *
6  * _| |_ _| |__/ | _| |_ _| |_\ |_ _| | \ \_ *
7  * |_____| |________| |_____| |_____|\____| |____||____| *
8  * *
9  *******************************************************************
10  * *
11  * fLink userspace library, base functionality *
12  * *
13  *******************************************************************/
14 
25 #include "flinklib.h"
26 #include "flinkioctl.h"
27 #include "types.h"
28 #include "valid.h"
29 #include "error.h"
30 #include "log.h"
31 
32 #include <stdlib.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 
36 
37 /*******************************************************************
38  * *
39  * Internal (private) methods *
40  * *
41  *******************************************************************/
42 
49 static int read_nof_subdevices(flink_dev* dev) {
50  uint8_t n = 0;
51 
52  dbg_print("reading number of subdevices...\n");
53 
54  if(flink_ioctl(dev, READ_NOF_SUBDEVICES, &n) < 0) {
55  dbg_print(" --> failed!\n");
56  libc_error();
57  return EXIT_ERROR;
58  }
59  dbg_print(" --> %u\n", n);
60  return n;
61 }
62 
69 static int get_subdevices(flink_dev* dev) {
70  flink_subdev* subdev = NULL;
71  int i = 0, ret = 0;
72 
73  if(!validate_flink_dev(dev)) {
75  return EXIT_ERROR;
76  }
77 
78  // Read nof subdevices
79  dev->nof_subdevices = read_nof_subdevices(dev);
80 
81  // Allocate memory
82  dev->subdevices = calloc(dev->nof_subdevices, sizeof(flink_subdev));
83  if(dev->subdevices == NULL) { // allocation failed
84  libc_error();
85  dev->nof_subdevices = 0;
86  return EXIT_ERROR;
87  }
88 
89  // Fillup all information
90  for(i = 0; i < dev->nof_subdevices; i++) { // for each subdevice
91  subdev = dev->subdevices + i;
92  subdev->id = i;
93  ret = flink_ioctl(dev, READ_SUBDEVICE_INFO, subdev);
94  if (ret < 0) return ret;
95  subdev->parent = dev;
96  }
97 
98  return i;
99 }
100 
101 
102 /*******************************************************************
103  * *
104  * Public methods *
105  * *
106  *******************************************************************/
107 
113 flink_dev* flink_open(const char* file_name) {
114  flink_dev* dev = NULL;
115 
116  // Allocate memory for flink_t
117  dev = malloc(sizeof(flink_dev));
118  if(dev == NULL) { // allocation failed
119  libc_error();
120  return NULL;
121  }
122 
123  // Open device file
124  dev->fd = open(file_name, O_RDWR);
125  if(dev->fd < 0) { // failed to open device
126  free(dev);
127  libc_error();
128  return NULL;
129  }
130 
131  if(get_subdevices(dev) < 0) { // reading subdevices failed
132  close(dev->fd);
133  free(dev);
134  return NULL;
135  }
136 
137  return dev;
138 }
139 
140 
147  if(!validate_flink_dev(dev)) {
149  return EXIT_ERROR;
150  }
151 
152  if(dev->subdevices) {
153  free(dev->subdevices);
154  }
155 
156  close(dev->fd);
157  free(dev);
158  return EXIT_SUCCESS;
159 }
160 
161 
168 
169  if(!validate_flink_dev(dev)) {
171  return EXIT_ERROR;
172  }
173 
174  return dev->nof_subdevices;
175 }
176 
177 
184  uint32_t offset = CONFIG_OFFSET;
185  uint8_t reset = 1;
186 
187  if(!validate_flink_subdev(subdev)) {
189  return EXIT_ERROR;
190  }
191 
192  if(flink_write_bit(subdev, offset, RESET_BIT, &reset)) {
193  libc_error();
194  return EXIT_ERROR;
195  }
196  return EXIT_SUCCESS;
197 }
198 
199 
206 int flink_subdevice_select(flink_subdev* subdev, uint8_t exclusive) {
207  ioctl_cmd_t cmd = SELECT_SUBDEVICE;
208  if(exclusive) cmd = SELECT_SUBDEVICE_EXCL;
209 
210  if(flink_ioctl(subdev->parent, cmd, &(subdev->id)) < 0) {
211  libc_error();
212  return EXIT_ERROR;
213  }
214  return EXIT_SUCCESS;
215 }
216 
224 
225  // Check flink device structure
226  if(!validate_flink_dev(dev)) {
228  return NULL;
229  }
230 
231  // Check subdevice id
232  if(subdev_id > dev->nof_subdevices) {
234  return NULL;
235  }
236 
237  return dev->subdevices + subdev_id;
238 }
239 
247  flink_subdev* subdev = dev->subdevices;
248 
249  // Check flink device structure
250  if(!validate_flink_dev(dev)) {
252  return NULL;
253  }
254 
255  uint8_t nof = 0;
256  while(nof++ < dev->nof_subdevices) {
257  if(subdev->unique_id == unique_id) {
258  return subdev;
259  }
260  subdev = subdev + 1;
261  }
262  return NULL;
263 }
264 
271  return subdev->id;
272 }
273 
280  return subdev->function_id;
281 }
282 
289  return subdev->sub_function_id;
290 }
291 
298  return subdev->function_version;
299 }
300 
307  return subdev->base_addr;
308 }
309 
316  return subdev->mem_size;
317 }
318 
325  return subdev->nof_channels;
326 }
327 
334  return subdev->unique_id;
335 }
flink_subdev * flink_get_subdevice_by_id(flink_dev *dev, uint8_t subdev_id)
Find subdevice of a device with a given id.
Definition: base.c:223
Data structures for flink devices and subdevices.
flink_subdev * flink_get_subdevice_by_unique_id(flink_dev *dev, uint32_t unique_id)
Find subdevice of a device with a given unique id.
Definition: base.c:246
flink_dev * flink_open(const char *file_name)
Opens a flink device file.
Definition: base.c:113
int flink_close(flink_dev *dev)
Close an open flink device.
Definition: base.c:146
int flink_subdevice_select(flink_subdev *subdev, uint8_t exclusive)
Select a flink subdevice for further operations.
Definition: base.c:206
uint32_t flink_subdevice_get_nofchannels(flink_subdev *subdev)
Get the number of channels of a subdevice.
Definition: base.c:324
#define FLINK_EINVALDEV
Definition: error.h:29
#define EXIT_ERROR
Definition: flinklib.h:129
uint8_t flink_subdevice_get_id(flink_subdev *subdev)
Get the id of a subdevice.
Definition: base.c:270
Error handling.
uint8_t flink_subdevice_get_subfunction(flink_subdev *subdev)
Get the subfunction of a subdevice.
Definition: base.c:288
#define CONFIG_OFFSET
Definition: flinklib.h:54
uint16_t flink_subdevice_get_function(flink_subdev *subdev)
Get the function of a subdevice.
Definition: base.c:279
uint8_t flink_subdevice_get_function_version(flink_subdev *subdev)
Get the function version of a subdevice.
Definition: base.c:297
flink userspace library, ioctl definitions.
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
#define EXIT_SUCCESS
Definition: flinklib.h:128
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
#define FLINK_EINVALSUBDEV
Definition: error.h:30
Contains validation functions for flink.
int flink_subdevice_reset(flink_subdev *subdev)
Reset a flink subdevice.
Definition: base.c:183
uint32_t flink_subdevice_get_unique_id(flink_subdev *subdev)
Get the unique id of a subdevice.
Definition: base.c:333
#define RESET_BIT
Definition: flinklib.h:63
flink_dev * dev
void flink_error(int e)
Definition: error.c:64
uint32_t flink_subdevice_get_memsize(flink_subdev *subdev)
Get the memory size of a subdevice.
Definition: base.c:315
int validate_flink_dev(flink_dev *dev)
Checks if flink device was opened.
Definition: valid.c:28
void libc_error(void)
Definition: error.c:56
int flink_get_nof_subdevices(flink_dev *dev)
Returns the number of subdevices of a fink device.
Definition: base.c:167
Debug utilities.
uint32_t flink_subdevice_get_baseaddr(flink_subdev *subdev)
Get the base address of a subdevice.
Definition: base.c:306
#define dbg_print(fmt,...)
Definition: log.h:29