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/>.
24 #include "libjaylink.h"
25 #include "libjaylink-internal.h"
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
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.
77 JAYLINK_API
int jaylink_file_read(struct jaylink_device_handle
*devh
,
78 const char *filename
, uint8_t *buffer
, uint32_t offset
,
82 struct jaylink_context
*ctx
;
83 uint8_t buf
[18 + JAYLINK_FILE_NAME_MAX_LENGTH
];
84 size_t filename_length
;
87 if (!devh
|| !filename
|| !buffer
|| !length
)
88 return JAYLINK_ERR_ARG
;
91 return JAYLINK_ERR_ARG
;
93 if (*length
> JAYLINK_FILE_MAX_TRANSFER_SIZE
)
94 return JAYLINK_ERR_ARG
;
96 filename_length
= strlen(filename
);
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
));
113 buf
[0] = CMD_FILE_IO
;
114 buf
[1] = FILE_IO_CMD_READ
;
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
));
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
));
147 ret
= transport_read(devh
, buffer
, *length
);
149 if (ret
!= JAYLINK_OK
) {
150 log_err(ctx
, "transport_read() failed: %s",
151 jaylink_strerror(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
));
163 ret
= transport_read(devh
, buf
, 4);
165 if (ret
!= JAYLINK_OK
) {
166 log_err(ctx
, "transport_read() failed: %s",
167 jaylink_strerror(ret
));
171 tmp
= buffer_get_u32(buf
, 0);
173 if (tmp
& FILE_IO_ERR
)
174 return JAYLINK_ERR_DEV
;
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.
212 JAYLINK_API
int jaylink_file_write(struct jaylink_device_handle
*devh
,
213 const char *filename
, const uint8_t *buffer
, uint32_t offset
,
217 struct jaylink_context
*ctx
;
218 uint8_t buf
[18 + JAYLINK_FILE_NAME_MAX_LENGTH
];
219 size_t filename_length
;
222 if (!devh
|| !filename
|| !buffer
|| !length
)
223 return JAYLINK_ERR_ARG
;
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
));
248 buf
[0] = CMD_FILE_IO
;
249 buf
[1] = FILE_IO_CMD_WRITE
;
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
));
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
));
282 ret
= transport_write(devh
, buffer
, *length
);
284 if (ret
!= JAYLINK_OK
) {
285 log_err(ctx
, "transport_write() failed: %s",
286 jaylink_strerror(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
));
298 ret
= transport_read(devh
, buf
, 4);
300 if (ret
!= JAYLINK_OK
) {
301 log_err(ctx
, "transport_read() failed: %s",
302 jaylink_strerror(ret
));
306 tmp
= buffer_get_u32(buf
, 0);
308 if (tmp
& FILE_IO_ERR
)
309 return JAYLINK_ERR_DEV
;
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
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.
338 JAYLINK_API
int jaylink_file_get_size(struct jaylink_device_handle
*devh
,
339 const char *filename
, uint32_t *size
)
342 struct jaylink_context
*ctx
;
343 uint8_t buf
[6 + JAYLINK_FILE_NAME_MAX_LENGTH
];
347 if (!devh
|| !filename
|| !size
)
348 return JAYLINK_ERR_ARG
;
350 length
= strlen(filename
);
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
));
367 buf
[0] = CMD_FILE_IO
;
368 buf
[1] = FILE_IO_CMD_GET_SIZE
;
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
));
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
));
393 ret
= transport_read(devh
, buf
, 4);
395 if (ret
!= JAYLINK_OK
) {
396 log_err(ctx
, "transport_read() failed: %s",
397 jaylink_strerror(ret
));
401 tmp
= buffer_get_u32(buf
, 0);
403 if (tmp
& FILE_IO_ERR
)
404 return JAYLINK_ERR_DEV
;
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.
430 JAYLINK_API
int jaylink_file_delete(struct jaylink_device_handle
*devh
,
431 const char *filename
)
434 struct jaylink_context
*ctx
;
435 uint8_t buf
[6 + JAYLINK_FILE_NAME_MAX_LENGTH
];
439 if (!devh
|| !filename
)
440 return JAYLINK_ERR_ARG
;
442 length
= strlen(filename
);
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
));
459 buf
[0] = CMD_FILE_IO
;
460 buf
[1] = FILE_IO_CMD_DELETE
;
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
));
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
));
485 ret
= transport_read(devh
, buf
, 4);
487 if (ret
!= JAYLINK_OK
) {
488 log_err(ctx
, "transport_read() failed: %s",
489 jaylink_strerror(ret
));
493 tmp
= buffer_get_u32(buf
, 0);
495 if (tmp
& FILE_IO_ERR
)
496 return JAYLINK_ERR_DEV
;