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/>.
25 #include "libjaylink.h"
26 #include "libjaylink-internal.h"
35 #define CMD_FILE_IO 0x1e
37 #define FILE_IO_CMD_READ 0x64
38 #define FILE_IO_CMD_WRITE 0x65
39 #define FILE_IO_CMD_GET_SIZE 0x66
40 #define FILE_IO_CMD_DELETE 0x67
42 #define FILE_IO_PARAM_FILENAME 0x01
43 #define FILE_IO_PARAM_OFFSET 0x02
44 #define FILE_IO_PARAM_LENGTH 0x03
46 #define FILE_IO_ERR 0x80000000
52 * The maximum amount of data that can be read from a file at once is
53 * #JAYLINK_FILE_MAX_TRANSFER_SIZE bytes. Multiple reads in conjunction with
54 * the @p offset parameter are needed for larger files.
56 * @note This function must only be used if the device has the
57 * #JAYLINK_DEV_CAP_FILE_IO capability.
59 * @param[in,out] devh Device handle.
60 * @param[in] filename Name of the file to read from. The length of the name
61 * must not exceed #JAYLINK_FILE_NAME_MAX_LENGTH bytes.
62 * @param[out] buffer Buffer to store read data.
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_DEV Unspecified device error, or the file was not found.
72 * @retval JAYLINK_ERR Other error conditions.
76 JAYLINK_API
int jaylink_file_read(struct jaylink_device_handle
*devh
,
77 const char *filename
, uint8_t *buffer
, uint32_t offset
,
81 struct jaylink_context
*ctx
;
82 uint8_t buf
[18 + JAYLINK_FILE_NAME_MAX_LENGTH
];
83 size_t filename_length
;
86 if (!devh
|| !filename
|| !buffer
|| !length
)
87 return JAYLINK_ERR_ARG
;
90 return JAYLINK_ERR_ARG
;
92 if (*length
> JAYLINK_FILE_MAX_TRANSFER_SIZE
)
93 return JAYLINK_ERR_ARG
;
95 filename_length
= strlen(filename
);
98 return JAYLINK_ERR_ARG
;
100 if (filename_length
> JAYLINK_FILE_NAME_MAX_LENGTH
)
101 return JAYLINK_ERR_ARG
;
103 ctx
= devh
->dev
->ctx
;
104 ret
= transport_start_write(devh
, 18 + filename_length
, true);
106 if (ret
!= JAYLINK_OK
) {
107 log_err(ctx
, "transport_start_write() failed: %i.", ret
);
111 buf
[0] = CMD_FILE_IO
;
112 buf
[1] = FILE_IO_CMD_READ
;
115 buf
[3] = filename_length
;
116 buf
[4] = FILE_IO_PARAM_FILENAME
;
117 memcpy(buf
+ 5, filename
, filename_length
);
119 buf
[filename_length
+ 5] = 0x04;
120 buf
[filename_length
+ 6] = FILE_IO_PARAM_OFFSET
;
121 buffer_set_u32(buf
, offset
, filename_length
+ 7);
123 buf
[filename_length
+ 11] = 0x04;
124 buf
[filename_length
+ 12] = FILE_IO_PARAM_LENGTH
;
125 buffer_set_u32(buf
, *length
, filename_length
+ 13);
127 buf
[filename_length
+ 17] = 0x00;
129 ret
= transport_write(devh
, buf
, 18 + filename_length
);
131 if (ret
!= JAYLINK_OK
) {
132 log_err(ctx
, "transport_write() failed: %i.", ret
);
136 ret
= transport_start_read(devh
, *length
);
138 if (ret
!= JAYLINK_OK
) {
139 log_err(ctx
, "transport_start_read() failed: %i.", ret
);
143 ret
= transport_read(devh
, buffer
, *length
);
145 if (ret
!= JAYLINK_OK
) {
146 log_err(ctx
, "transport_read() failed: %i.", ret
);
150 ret
= transport_start_read(devh
, 4);
152 if (ret
!= JAYLINK_OK
) {
153 log_err(ctx
, "transport_start_read() failed: %i.", ret
);
157 ret
= transport_read(devh
, buf
, 4);
159 if (ret
!= JAYLINK_OK
) {
160 log_err(ctx
, "transport_read() failed: %i.", ret
);
164 tmp
= buffer_get_u32(buf
, 0);
166 if (tmp
& FILE_IO_ERR
)
167 return JAYLINK_ERR_DEV
;
177 * If a file does not exist, a new file is created.
179 * The maximum amount of data that can be written to a file at once is
180 * #JAYLINK_FILE_MAX_TRANSFER_SIZE bytes. Multiple writes in conjunction with
181 * the @p offset parameter are needed for larger files.
183 * @note This function must only be used if the device has the
184 * #JAYLINK_DEV_CAP_FILE_IO capability.
186 * @param[in,out] devh Device handle.
187 * @param[in] filename Name of the file to write to. The length of the name
188 * must not exceed #JAYLINK_FILE_NAME_MAX_LENGTH bytes.
189 * @param[in] buffer Buffer to write data from.
190 * @param[in] offset Offset in bytes relative to the beginning of the file from
191 * where to start writing.
192 * @param[in,out] length Number of bytes to write. On success, the value gets
193 * updated with the actual number of bytes written. The
194 * value is undefined on failure.
196 * @retval JAYLINK_OK Success.
197 * @retval JAYLINK_ERR_ARG Invalid arguments.
198 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
199 * @retval JAYLINK_ERR_DEV Unspecified device error, or the file was not found.
200 * @retval JAYLINK_ERR Other error conditions.
204 JAYLINK_API
int jaylink_file_write(struct jaylink_device_handle
*devh
,
205 const char *filename
, const uint8_t *buffer
, uint32_t offset
,
209 struct jaylink_context
*ctx
;
210 uint8_t buf
[18 + JAYLINK_FILE_NAME_MAX_LENGTH
];
211 size_t filename_length
;
214 if (!devh
|| !filename
|| !buffer
|| !length
)
215 return JAYLINK_ERR_ARG
;
218 return JAYLINK_ERR_ARG
;
220 if (*length
> JAYLINK_FILE_MAX_TRANSFER_SIZE
)
221 return JAYLINK_ERR_ARG
;
223 filename_length
= strlen(filename
);
225 if (!filename_length
)
226 return JAYLINK_ERR_ARG
;
228 if (filename_length
> JAYLINK_FILE_NAME_MAX_LENGTH
)
229 return JAYLINK_ERR_ARG
;
231 ctx
= devh
->dev
->ctx
;
232 ret
= transport_start_write(devh
, 18 + filename_length
, true);
234 if (ret
!= JAYLINK_OK
) {
235 log_err(ctx
, "transport_start_write() failed: %i.", ret
);
239 buf
[0] = CMD_FILE_IO
;
240 buf
[1] = FILE_IO_CMD_WRITE
;
243 buf
[3] = filename_length
;
244 buf
[4] = FILE_IO_PARAM_FILENAME
;
245 memcpy(buf
+ 5, filename
, filename_length
);
247 buf
[filename_length
+ 5] = 0x04;
248 buf
[filename_length
+ 6] = FILE_IO_PARAM_OFFSET
;
249 buffer_set_u32(buf
, offset
, filename_length
+ 7);
251 buf
[filename_length
+ 11] = 0x04;
252 buf
[filename_length
+ 12] = FILE_IO_PARAM_LENGTH
;
253 buffer_set_u32(buf
, *length
, filename_length
+ 13);
255 buf
[filename_length
+ 17] = 0x00;
257 ret
= transport_write(devh
, buf
, 18 + filename_length
);
259 if (ret
!= JAYLINK_OK
) {
260 log_err(ctx
, "transport_write() failed: %i.", ret
);
264 ret
= transport_start_write(devh
, *length
, true);
266 if (ret
!= JAYLINK_OK
) {
267 log_err(ctx
, "transport_start_write() failed: %i.", ret
);
271 ret
= transport_write(devh
, buffer
, *length
);
273 if (ret
!= JAYLINK_OK
) {
274 log_err(ctx
, "transport_write() failed: %i.", ret
);
278 ret
= transport_start_read(devh
, 4);
280 if (ret
!= JAYLINK_OK
) {
281 log_err(ctx
, "transport_start_read() failed: %i.", ret
);
285 ret
= transport_read(devh
, buf
, 4);
287 if (ret
!= JAYLINK_OK
) {
288 log_err(ctx
, "transport_read() failed: %i.", ret
);
292 tmp
= buffer_get_u32(buf
, 0);
294 if (tmp
& FILE_IO_ERR
)
295 return JAYLINK_ERR_DEV
;
303 * Retrieve the size of a file.
305 * @note This function must only be used if the device has the
306 * #JAYLINK_DEV_CAP_FILE_IO capability.
308 * @param[in,out] devh Device handle.
309 * @param[in] filename Name of the file to retrieve the size of. The length
310 * of the name must not exceed
311 * #JAYLINK_FILE_NAME_MAX_LENGTH bytes.
312 * @param[out] size Size of the file in bytes on success, and undefined on
315 * @retval JAYLINK_OK Success.
316 * @retval JAYLINK_ERR_ARG Invalid arguments.
317 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
318 * @retval JAYLINK_ERR_DEV Unspecified device error, or the file was not found.
319 * @retval JAYLINK_ERR Other error conditions.
323 JAYLINK_API
int jaylink_file_get_size(struct jaylink_device_handle
*devh
,
324 const char *filename
, uint32_t *size
)
327 struct jaylink_context
*ctx
;
328 uint8_t buf
[6 + JAYLINK_FILE_NAME_MAX_LENGTH
];
332 if (!devh
|| !filename
|| !size
)
333 return JAYLINK_ERR_ARG
;
335 length
= strlen(filename
);
338 return JAYLINK_ERR_ARG
;
340 if (length
> JAYLINK_FILE_NAME_MAX_LENGTH
)
341 return JAYLINK_ERR_ARG
;
343 ctx
= devh
->dev
->ctx
;
344 ret
= transport_start_write(devh
, 6 + length
, true);
346 if (ret
!= JAYLINK_OK
) {
347 log_err(ctx
, "transport_start_write() failed: %i.", ret
);
351 buf
[0] = CMD_FILE_IO
;
352 buf
[1] = FILE_IO_CMD_GET_SIZE
;
356 buf
[4] = FILE_IO_PARAM_FILENAME
;
357 memcpy(buf
+ 5, filename
, length
);
359 buf
[length
+ 5] = 0x00;
361 ret
= transport_write(devh
, buf
, 6 + length
);
363 if (ret
!= JAYLINK_OK
) {
364 log_err(ctx
, "transport_write() failed: %i.", ret
);
368 ret
= transport_start_read(devh
, 4);
370 if (ret
!= JAYLINK_OK
) {
371 log_err(ctx
, "transport_start_read() failed: %i.", ret
);
375 ret
= transport_read(devh
, buf
, 4);
377 if (ret
!= JAYLINK_OK
) {
378 log_err(ctx
, "transport_read() failed: %i.", ret
);
382 tmp
= buffer_get_u32(buf
, 0);
384 if (tmp
& FILE_IO_ERR
)
385 return JAYLINK_ERR_DEV
;
395 * @note This function must only be used if the device has the
396 * #JAYLINK_DEV_CAP_FILE_IO capability.
398 * @param[in,out] devh Device handle.
399 * @param[in] filename Name of the file to delete. The length of the name
400 * must not exceed #JAYLINK_FILE_NAME_MAX_LENGTH bytes.
402 * @retval JAYLINK_OK Success.
403 * @retval JAYLINK_ERR_ARG Invalid arguments.
404 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
405 * @retval JAYLINK_ERR_DEV Unspecified device error, or the file was not found.
406 * @retval JAYLINK_ERR Other error conditions.
410 JAYLINK_API
int jaylink_file_delete(struct jaylink_device_handle
*devh
,
411 const char *filename
)
414 struct jaylink_context
*ctx
;
415 uint8_t buf
[6 + JAYLINK_FILE_NAME_MAX_LENGTH
];
419 if (!devh
|| !filename
)
420 return JAYLINK_ERR_ARG
;
422 length
= strlen(filename
);
425 return JAYLINK_ERR_ARG
;
427 if (length
> JAYLINK_FILE_NAME_MAX_LENGTH
)
428 return JAYLINK_ERR_ARG
;
430 ctx
= devh
->dev
->ctx
;
431 ret
= transport_start_write(devh
, 6 + length
, true);
433 if (ret
!= JAYLINK_OK
) {
434 log_err(ctx
, "transport_start_write() failed: %i.", ret
);
438 buf
[0] = CMD_FILE_IO
;
439 buf
[1] = FILE_IO_CMD_DELETE
;
443 buf
[4] = FILE_IO_PARAM_FILENAME
;
444 memcpy(buf
+ 5, filename
, length
);
446 buf
[length
+ 5] = 0x00;
448 ret
= transport_write(devh
, buf
, 6 + length
);
450 if (ret
!= JAYLINK_OK
) {
451 log_err(ctx
, "transport_write() failed: %i.", ret
);
455 ret
= transport_start_read(devh
, 4);
457 if (ret
!= JAYLINK_OK
) {
458 log_err(ctx
, "transport_start_read() failed: %i.", ret
);
462 ret
= transport_read(devh
, buf
, 4);
464 if (ret
!= JAYLINK_OK
) {
465 log_err(ctx
, "transport_read() failed: %i.", ret
);
469 tmp
= buffer_get_u32(buf
, 0);
471 if (tmp
& FILE_IO_ERR
)
472 return JAYLINK_ERR_DEV
;