Add jaylink_device_get_usb_bus_ports()
[libjaylink.git] / libjaylink / fileio.c
blob933c36630e1d1c844655adf8cdd0b4937a8812be
1 /*
2 * This file is part of the libjaylink project.
4 * Copyright (C) 2015 Marc Schink <jaylink-dev@marcschink.de>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <stdint.h>
21 #include <stdbool.h>
22 #include <string.h>
24 #include "libjaylink.h"
25 #include "libjaylink-internal.h"
27 /**
28 * @file
30 * File I/O functions.
33 /** @cond PRIVATE */
34 #define CMD_FILE_IO 0x1e
36 #define FILE_IO_CMD_READ 0x64
37 #define FILE_IO_CMD_WRITE 0x65
38 #define FILE_IO_CMD_GET_SIZE 0x66
39 #define FILE_IO_CMD_DELETE 0x67
41 #define FILE_IO_PARAM_FILENAME 0x01
42 #define FILE_IO_PARAM_OFFSET 0x02
43 #define FILE_IO_PARAM_LENGTH 0x03
45 #define FILE_IO_ERR 0x80000000
46 /** @endcond */
48 /**
49 * Read from a file.
51 * The maximum amount of data that can be read from a file at once is
52 * #JAYLINK_FILE_MAX_TRANSFER_SIZE bytes. Multiple reads in conjunction with
53 * the @p offset parameter are needed for larger files.
55 * @note This function must only be used if the device has the
56 * #JAYLINK_DEV_CAP_FILE_IO capability.
58 * @param[in,out] devh Device handle.
59 * @param[in] filename Name of the file to read from. The length of the name
60 * must not exceed #JAYLINK_FILE_NAME_MAX_LENGTH bytes.
61 * @param[out] buffer Buffer to store read data on success. Its content is
62 * undefined on failure
63 * @param[in] offset Offset in bytes relative to the beginning of the file from
64 * where to start reading.
65 * @param[in,out] length Number of bytes to read. On success, the value gets
66 * updated with the actual number of bytes read. The
67 * value is undefined on failure.
68 * @retval JAYLINK_OK Success.
69 * @retval JAYLINK_ERR_ARG Invalid arguments.
70 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
71 * @retval JAYLINK_ERR_IO Input/output error.
72 * @retval JAYLINK_ERR_DEV Unspecified device error, or the file was not found.
73 * @retval JAYLINK_ERR Other error conditions.
75 * @since 0.1.0
77 JAYLINK_API int jaylink_file_read(struct jaylink_device_handle *devh,
78 const char *filename, uint8_t *buffer, uint32_t offset,
79 uint32_t *length)
81 int ret;
82 struct jaylink_context *ctx;
83 uint8_t buf[18 + JAYLINK_FILE_NAME_MAX_LENGTH];
84 size_t filename_length;
85 uint32_t tmp;
87 if (!devh || !filename || !buffer || !length)
88 return JAYLINK_ERR_ARG;
90 if (!*length)
91 return JAYLINK_ERR_ARG;
93 if (*length > JAYLINK_FILE_MAX_TRANSFER_SIZE)
94 return JAYLINK_ERR_ARG;
96 filename_length = strlen(filename);
98 if (!filename_length)
99 return JAYLINK_ERR_ARG;
101 if (filename_length > JAYLINK_FILE_NAME_MAX_LENGTH)
102 return JAYLINK_ERR_ARG;
104 ctx = devh->dev->ctx;
105 ret = transport_start_write(devh, 18 + filename_length, true);
107 if (ret != JAYLINK_OK) {
108 log_err(ctx, "transport_start_write() failed: %s.",
109 jaylink_strerror(ret));
110 return ret;
113 buf[0] = CMD_FILE_IO;
114 buf[1] = FILE_IO_CMD_READ;
115 buf[2] = 0x00;
117 buf[3] = filename_length;
118 buf[4] = FILE_IO_PARAM_FILENAME;
119 memcpy(buf + 5, filename, filename_length);
121 buf[filename_length + 5] = 0x04;
122 buf[filename_length + 6] = FILE_IO_PARAM_OFFSET;
123 buffer_set_u32(buf, offset, filename_length + 7);
125 buf[filename_length + 11] = 0x04;
126 buf[filename_length + 12] = FILE_IO_PARAM_LENGTH;
127 buffer_set_u32(buf, *length, filename_length + 13);
129 buf[filename_length + 17] = 0x00;
131 ret = transport_write(devh, buf, 18 + filename_length);
133 if (ret != JAYLINK_OK) {
134 log_err(ctx, "transport_write() failed: %s.",
135 jaylink_strerror(ret));
136 return ret;
139 ret = transport_start_read(devh, *length);
141 if (ret != JAYLINK_OK) {
142 log_err(ctx, "transport_start_read() failed: %s.",
143 jaylink_strerror(ret));
144 return ret;
147 ret = transport_read(devh, buffer, *length);
149 if (ret != JAYLINK_OK) {
150 log_err(ctx, "transport_read() failed: %s.",
151 jaylink_strerror(ret));
152 return ret;
155 ret = transport_start_read(devh, 4);
157 if (ret != JAYLINK_OK) {
158 log_err(ctx, "transport_start_read() failed: %s.",
159 jaylink_strerror(ret));
160 return ret;
163 ret = transport_read(devh, buf, 4);
165 if (ret != JAYLINK_OK) {
166 log_err(ctx, "transport_read() failed: %s.",
167 jaylink_strerror(ret));
168 return ret;
171 tmp = buffer_get_u32(buf, 0);
173 if (tmp & FILE_IO_ERR)
174 return JAYLINK_ERR_DEV;
176 *length = tmp;
178 return JAYLINK_OK;
182 * Write to a file.
184 * If a file does not exist, a new file is created.
186 * The maximum amount of data that can be written to a file at once is
187 * #JAYLINK_FILE_MAX_TRANSFER_SIZE bytes. Multiple writes in conjunction with
188 * the @p offset parameter are needed for larger files.
190 * @note This function must only be used if the device has the
191 * #JAYLINK_DEV_CAP_FILE_IO capability.
193 * @param[in,out] devh Device handle.
194 * @param[in] filename Name of the file to write to. The length of the name
195 * must not exceed #JAYLINK_FILE_NAME_MAX_LENGTH bytes.
196 * @param[in] buffer Buffer to write data from.
197 * @param[in] offset Offset in bytes relative to the beginning of the file from
198 * where to start writing.
199 * @param[in,out] length Number of bytes to write. On success, the value gets
200 * updated with the actual number of bytes written. The
201 * value is undefined on failure.
203 * @retval JAYLINK_OK Success.
204 * @retval JAYLINK_ERR_ARG Invalid arguments.
205 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
206 * @retval JAYLINK_ERR_IO Input/output error.
207 * @retval JAYLINK_ERR_DEV Unspecified device error, or the file was not found.
208 * @retval JAYLINK_ERR Other error conditions.
210 * @since 0.1.0
212 JAYLINK_API int jaylink_file_write(struct jaylink_device_handle *devh,
213 const char *filename, const uint8_t *buffer, uint32_t offset,
214 uint32_t *length)
216 int ret;
217 struct jaylink_context *ctx;
218 uint8_t buf[18 + JAYLINK_FILE_NAME_MAX_LENGTH];
219 size_t filename_length;
220 uint32_t tmp;
222 if (!devh || !filename || !buffer || !length)
223 return JAYLINK_ERR_ARG;
225 if (!*length)
226 return JAYLINK_ERR_ARG;
228 if (*length > JAYLINK_FILE_MAX_TRANSFER_SIZE)
229 return JAYLINK_ERR_ARG;
231 filename_length = strlen(filename);
233 if (!filename_length)
234 return JAYLINK_ERR_ARG;
236 if (filename_length > JAYLINK_FILE_NAME_MAX_LENGTH)
237 return JAYLINK_ERR_ARG;
239 ctx = devh->dev->ctx;
240 ret = transport_start_write(devh, 18 + filename_length, true);
242 if (ret != JAYLINK_OK) {
243 log_err(ctx, "transport_start_write() failed: %s.",
244 jaylink_strerror(ret));
245 return ret;
248 buf[0] = CMD_FILE_IO;
249 buf[1] = FILE_IO_CMD_WRITE;
250 buf[2] = 0x00;
252 buf[3] = filename_length;
253 buf[4] = FILE_IO_PARAM_FILENAME;
254 memcpy(buf + 5, filename, filename_length);
256 buf[filename_length + 5] = 0x04;
257 buf[filename_length + 6] = FILE_IO_PARAM_OFFSET;
258 buffer_set_u32(buf, offset, filename_length + 7);
260 buf[filename_length + 11] = 0x04;
261 buf[filename_length + 12] = FILE_IO_PARAM_LENGTH;
262 buffer_set_u32(buf, *length, filename_length + 13);
264 buf[filename_length + 17] = 0x00;
266 ret = transport_write(devh, buf, 18 + filename_length);
268 if (ret != JAYLINK_OK) {
269 log_err(ctx, "transport_write() failed: %s.",
270 jaylink_strerror(ret));
271 return ret;
274 ret = transport_start_write(devh, *length, true);
276 if (ret != JAYLINK_OK) {
277 log_err(ctx, "transport_start_write() failed: %s.",
278 jaylink_strerror(ret));
279 return ret;
282 ret = transport_write(devh, buffer, *length);
284 if (ret != JAYLINK_OK) {
285 log_err(ctx, "transport_write() failed: %s.",
286 jaylink_strerror(ret));
287 return ret;
290 ret = transport_start_read(devh, 4);
292 if (ret != JAYLINK_OK) {
293 log_err(ctx, "transport_start_read() failed: %s.",
294 jaylink_strerror(ret));
295 return ret;
298 ret = transport_read(devh, buf, 4);
300 if (ret != JAYLINK_OK) {
301 log_err(ctx, "transport_read() failed: %s.",
302 jaylink_strerror(ret));
303 return ret;
306 tmp = buffer_get_u32(buf, 0);
308 if (tmp & FILE_IO_ERR)
309 return JAYLINK_ERR_DEV;
311 *length = tmp;
313 return JAYLINK_OK;
317 * Retrieve the size of a file.
319 * @note This function must only be used if the device has the
320 * #JAYLINK_DEV_CAP_FILE_IO capability.
322 * @param[in,out] devh Device handle.
323 * @param[in] filename Name of the file to retrieve the size of. The length
324 * of the name must not exceed
325 * #JAYLINK_FILE_NAME_MAX_LENGTH bytes.
326 * @param[out] size Size of the file in bytes on success, and undefined on
327 * failure.
329 * @retval JAYLINK_OK Success.
330 * @retval JAYLINK_ERR_ARG Invalid arguments.
331 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
332 * @retval JAYLINK_ERR_IO Input/output error.
333 * @retval JAYLINK_ERR_DEV Unspecified device error, or the file was not found.
334 * @retval JAYLINK_ERR Other error conditions.
336 * @since 0.1.0
338 JAYLINK_API int jaylink_file_get_size(struct jaylink_device_handle *devh,
339 const char *filename, uint32_t *size)
341 int ret;
342 struct jaylink_context *ctx;
343 uint8_t buf[6 + JAYLINK_FILE_NAME_MAX_LENGTH];
344 size_t length;
345 uint32_t tmp;
347 if (!devh || !filename || !size)
348 return JAYLINK_ERR_ARG;
350 length = strlen(filename);
352 if (!length)
353 return JAYLINK_ERR_ARG;
355 if (length > JAYLINK_FILE_NAME_MAX_LENGTH)
356 return JAYLINK_ERR_ARG;
358 ctx = devh->dev->ctx;
359 ret = transport_start_write(devh, 6 + length, true);
361 if (ret != JAYLINK_OK) {
362 log_err(ctx, "transport_start_write() failed: %s.",
363 jaylink_strerror(ret));
364 return ret;
367 buf[0] = CMD_FILE_IO;
368 buf[1] = FILE_IO_CMD_GET_SIZE;
369 buf[2] = 0x00;
371 buf[3] = length;
372 buf[4] = FILE_IO_PARAM_FILENAME;
373 memcpy(buf + 5, filename, length);
375 buf[length + 5] = 0x00;
377 ret = transport_write(devh, buf, 6 + length);
379 if (ret != JAYLINK_OK) {
380 log_err(ctx, "transport_write() failed: %s.",
381 jaylink_strerror(ret));
382 return ret;
385 ret = transport_start_read(devh, 4);
387 if (ret != JAYLINK_OK) {
388 log_err(ctx, "transport_start_read() failed: %s.",
389 jaylink_strerror(ret));
390 return ret;
393 ret = transport_read(devh, buf, 4);
395 if (ret != JAYLINK_OK) {
396 log_err(ctx, "transport_read() failed: %s.",
397 jaylink_strerror(ret));
398 return ret;
401 tmp = buffer_get_u32(buf, 0);
403 if (tmp & FILE_IO_ERR)
404 return JAYLINK_ERR_DEV;
406 *size = tmp;
408 return JAYLINK_OK;
412 * Delete a file.
414 * @note This function must only be used if the device has the
415 * #JAYLINK_DEV_CAP_FILE_IO capability.
417 * @param[in,out] devh Device handle.
418 * @param[in] filename Name of the file to delete. The length of the name
419 * must not exceed #JAYLINK_FILE_NAME_MAX_LENGTH bytes.
421 * @retval JAYLINK_OK Success.
422 * @retval JAYLINK_ERR_ARG Invalid arguments.
423 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
424 * @retval JAYLINK_ERR_IO Input/output error.
425 * @retval JAYLINK_ERR_DEV Unspecified device error, or the file was not found.
426 * @retval JAYLINK_ERR Other error conditions.
428 * @since 0.1.0
430 JAYLINK_API int jaylink_file_delete(struct jaylink_device_handle *devh,
431 const char *filename)
433 int ret;
434 struct jaylink_context *ctx;
435 uint8_t buf[6 + JAYLINK_FILE_NAME_MAX_LENGTH];
436 size_t length;
437 uint32_t tmp;
439 if (!devh || !filename)
440 return JAYLINK_ERR_ARG;
442 length = strlen(filename);
444 if (!length)
445 return JAYLINK_ERR_ARG;
447 if (length > JAYLINK_FILE_NAME_MAX_LENGTH)
448 return JAYLINK_ERR_ARG;
450 ctx = devh->dev->ctx;
451 ret = transport_start_write(devh, 6 + length, true);
453 if (ret != JAYLINK_OK) {
454 log_err(ctx, "transport_start_write() failed: %s.",
455 jaylink_strerror(ret));
456 return ret;
459 buf[0] = CMD_FILE_IO;
460 buf[1] = FILE_IO_CMD_DELETE;
461 buf[2] = 0x00;
463 buf[3] = length;
464 buf[4] = FILE_IO_PARAM_FILENAME;
465 memcpy(buf + 5, filename, length);
467 buf[length + 5] = 0x00;
469 ret = transport_write(devh, buf, 6 + length);
471 if (ret != JAYLINK_OK) {
472 log_err(ctx, "transport_write() failed: %s.",
473 jaylink_strerror(ret));
474 return ret;
477 ret = transport_start_read(devh, 4);
479 if (ret != JAYLINK_OK) {
480 log_err(ctx, "transport_start_read() failed: %s.",
481 jaylink_strerror(ret));
482 return ret;
485 ret = transport_read(devh, buf, 4);
487 if (ret != JAYLINK_OK) {
488 log_err(ctx, "transport_read() failed: %s.",
489 jaylink_strerror(ret));
490 return ret;
493 tmp = buffer_get_u32(buf, 0);
495 if (tmp & FILE_IO_ERR)
496 return JAYLINK_ERR_DEV;
498 return JAYLINK_OK;