-
Notifications
You must be signed in to change notification settings - Fork 138
Expand file tree
/
Copy pathio.c
More file actions
142 lines (122 loc) · 3.43 KB
/
io.c
File metadata and controls
142 lines (122 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "qdl.h"
struct qdl_device *qdl_init(enum QDL_DEVICE_TYPE type)
{
if (type == QDL_DEVICE_USB)
return usb_init();
if (type == QDL_DEVICE_SIM)
return sim_init();
if (type == QDL_DEVICE_QUD)
return qud_init();
if (type == QDL_DEVICE_AUTO)
return auto_init();
return NULL;
}
void qdl_deinit(struct qdl_device *qdl)
{
if (qdl) {
free(qdl->pending_buf);
free(qdl);
}
}
void qdl_set_out_chunk_size(struct qdl_device *qdl, long size)
{
qdl->set_out_chunk_size(qdl, size);
}
int qdl_open(struct qdl_device *qdl, const char *serial)
{
return qdl->open(qdl, serial);
}
void qdl_close(struct qdl_device *qdl)
{
qdl->close(qdl);
}
/**
* qdl_read() - Read a message from the device
* @qdl: device handle
* @buf: buffer to write the data into
* @len: maximum length of data to be read
* @timeout: timeout for the read, in milliseconds
*
* Drains the pushback buffer (qdl_push_back()) before touching the underlying
* transport, so a previous read that crossed a Firehose message boundary can
* deliver the trailing bytes here.
*
* Returns: number of bytes read, might be zero for a ZLP
* negative errno on failure (notably -ETIMEDOUT)
*/
int qdl_read(struct qdl_device *qdl, void *buf, size_t len, unsigned int timeout)
{
size_t available;
size_t copy;
if (qdl->pending_buf) {
available = qdl->pending_len - qdl->pending_off;
copy = available < len ? available : len;
memcpy(buf, qdl->pending_buf + qdl->pending_off, copy);
qdl->pending_off += copy;
if (qdl->pending_off >= qdl->pending_len) {
free(qdl->pending_buf);
qdl->pending_buf = NULL;
qdl->pending_len = 0;
qdl->pending_off = 0;
}
return (int)copy;
}
return qdl->read(qdl, buf, len, timeout);
}
/**
* qdl_push_back() - Stash unread bytes for a future qdl_read()
* @qdl: device handle
* @buf: bytes to remember
* @len: number of bytes
*
* Concatenates @buf onto whatever is already pending (after any already-served
* prefix). Used by firehose_read() when a single transport read returned more
* than one Firehose message - or an XML envelope followed immediately by its
* rawmode binary payload - and we need the trailing bytes to surface on the
* next qdl_read() before any new transport I/O happens.
*
* Returns: 0 on success, negative errno on allocation failure.
*/
int qdl_push_back(struct qdl_device *qdl, const void *buf, size_t len)
{
char *grown;
size_t total;
if (!len)
return 0;
if (qdl->pending_off > 0) {
size_t leftover = qdl->pending_len - qdl->pending_off;
memmove(qdl->pending_buf, qdl->pending_buf + qdl->pending_off,
leftover);
qdl->pending_len = leftover;
qdl->pending_off = 0;
}
total = qdl->pending_len + len;
grown = realloc(qdl->pending_buf, total);
if (!grown)
return -ENOMEM;
memcpy(grown + qdl->pending_len, buf, len);
qdl->pending_buf = grown;
qdl->pending_len = total;
return 0;
}
/**
* qdl_write() - Write a message from the device
* @qdl: device handle
* @buf: buffer with data to be written
* @len: length of data to be written
* @timeout: timeout for write, in milliseconds
*
* Returns: number of bytes read
* negative errno on failure (notably -ETIMEDOUT)
*/
int qdl_write(struct qdl_device *qdl, const void *buf, size_t len, unsigned int timeout)
{
return qdl->write(qdl, buf, len, timeout);
}