OpenOCD
emucom.c
Go to the documentation of this file.
1 /*
2  * This file is part of the libjaylink project.
3  *
4  * Copyright (C) 2015-2016 Marc Schink <jaylink-dev@marcschink.de>
5  *
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.
10  *
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.
15  *
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/>.
18  */
19 
20 #include <stdint.h>
21 #include <stdbool.h>
22 
23 #include "libjaylink.h"
24 #include "libjaylink-internal.h"
25 
33 #define CMD_EMUCOM 0xee
34 
35 #define EMUCOM_CMD_READ 0x00
36 #define EMUCOM_CMD_WRITE 0x01
37 
39 #define EMUCOM_ERR 0x80000000
40 
42 #define EMUCOM_ERR_NOT_SUPPORTED 0x80000001
43 
53 #define EMUCOM_ERR_NOT_AVAILABLE 0x81000000
54 
59 #define EMUCOM_AVAILABLE_BYTES_MASK 0x00ffffff
60 
94  uint32_t channel, uint8_t *buffer, uint32_t *length)
95 {
96  int ret;
97  struct jaylink_context *ctx;
98  uint8_t buf[10];
99  uint32_t tmp;
100 
101  if (!devh || !buffer || !length)
102  return JAYLINK_ERR_ARG;
103 
104  ctx = devh->dev->ctx;
105  ret = transport_start_write_read(devh, 10, 4, true);
106 
107  if (ret != JAYLINK_OK) {
108  log_err(ctx, "transport_start_write_read() failed: %s.",
109  jaylink_strerror(ret));
110  return ret;
111  }
112 
113  buf[0] = CMD_EMUCOM;
114  buf[1] = EMUCOM_CMD_READ;
115 
116  buffer_set_u32(buf, channel, 2);
117  buffer_set_u32(buf, *length, 6);
118 
119  ret = transport_write(devh, buf, 10);
120 
121  if (ret != JAYLINK_OK) {
122  log_err(ctx, "transport_write() failed: %s.",
123  jaylink_strerror(ret));
124  return ret;
125  }
126 
127  ret = transport_read(devh, buf, 4);
128 
129  if (ret != JAYLINK_OK) {
130  log_err(ctx, "transport_read() failed: %s.",
131  jaylink_strerror(ret));
132  return ret;
133  }
134 
135  tmp = buffer_get_u32(buf, 0);
136 
137  if (tmp == EMUCOM_ERR_NOT_SUPPORTED)
139 
140  if ((tmp & ~EMUCOM_AVAILABLE_BYTES_MASK) == EMUCOM_ERR_NOT_AVAILABLE) {
141  *length = tmp & EMUCOM_AVAILABLE_BYTES_MASK;
143  }
144 
145  if (tmp & EMUCOM_ERR) {
146  log_err(ctx, "Failed to read from channel 0x%x: 0x%x.",
147  channel, tmp);
148  return JAYLINK_ERR_DEV;
149  }
150 
151  if (tmp > *length) {
152  log_err(ctx, "Requested at most %u bytes but device "
153  "returned %u bytes.", *length, tmp);
154  return JAYLINK_ERR_PROTO;
155  }
156 
157  *length = tmp;
158 
159  if (!tmp)
160  return JAYLINK_OK;
161 
162  ret = transport_start_read(devh, tmp);
163 
164  if (ret != JAYLINK_OK) {
165  log_err(ctx, "transport_start_read() failed: %s.",
166  jaylink_strerror(ret));
167  return ret;
168  }
169 
170  ret = transport_read(devh, buffer, tmp);
171 
172  if (ret != JAYLINK_OK) {
173  log_err(ctx, "transport_read() failed: %s.",
174  jaylink_strerror(ret));
175  return ret;
176  }
177 
178  return JAYLINK_OK;
179 }
180 
207  uint32_t channel, const uint8_t *buffer, uint32_t *length)
208 {
209  int ret;
210  struct jaylink_context *ctx;
211  uint8_t buf[10];
212  uint32_t tmp;
213 
214  if (!devh || !buffer || !length)
215  return JAYLINK_ERR_ARG;
216 
217  if (!*length)
218  return JAYLINK_ERR_ARG;
219 
220  ctx = devh->dev->ctx;
221  ret = transport_start_write(devh, 10, true);
222 
223  if (ret != JAYLINK_OK) {
224  log_err(ctx, "transport_start_write() failed: %s.",
225  jaylink_strerror(ret));
226  return ret;
227  }
228 
229  buf[0] = CMD_EMUCOM;
230  buf[1] = EMUCOM_CMD_WRITE;
231 
232  buffer_set_u32(buf, channel, 2);
233  buffer_set_u32(buf, *length, 6);
234 
235  ret = transport_write(devh, buf, 10);
236 
237  if (ret != JAYLINK_OK) {
238  log_err(ctx, "transport_write() failed: %s.",
239  jaylink_strerror(ret));
240  return ret;
241  }
242 
243  ret = transport_start_write_read(devh, *length, 4, false);
244 
245  if (ret != JAYLINK_OK) {
246  log_err(ctx, "transport_start_write_read() failed: %s.",
247  jaylink_strerror(ret));
248  return ret;
249  }
250 
251  ret = transport_write(devh, buffer, *length);
252 
253  if (ret != JAYLINK_OK) {
254  log_err(ctx, "transport_write() failed: %s.",
255  jaylink_strerror(ret));
256  return ret;
257  }
258 
259  ret = transport_read(devh, buf, 4);
260 
261  if (ret != JAYLINK_OK) {
262  log_err(ctx, "transport_read() failed: %s.",
263  jaylink_strerror(ret));
264  return ret;
265  }
266 
267  tmp = buffer_get_u32(buf, 0);
268 
269  if (tmp == EMUCOM_ERR_NOT_SUPPORTED)
271 
272  if (tmp & EMUCOM_ERR) {
273  log_err(ctx, "Failed to write to channel 0x%x: 0x%x.",
274  channel, tmp);
275  return JAYLINK_ERR_DEV;
276  }
277 
278  if (tmp > *length) {
279  log_err(ctx, "Only %u bytes were supposed to be written, but "
280  "the device reported %u written bytes.", *length, tmp);
281  return JAYLINK_ERR_PROTO;
282  }
283 
284  *length = tmp;
285 
286  return JAYLINK_OK;
287 }
JAYLINK_API int jaylink_emucom_read(struct jaylink_device_handle *devh, uint32_t channel, uint8_t *buffer, uint32_t *length)
Read from an EMUCOM channel.
Definition: emucom.c:93
JAYLINK_PRIV uint32_t buffer_get_u32(const uint8_t *buffer, size_t offset)
Read a 32-bit unsigned integer value from a buffer.
Definition: buffer.c:122
JAYLINK_API const char * jaylink_strerror(int error_code)
Return a human-readable description of a libjaylink error code.
Definition: error.c:40
JAYLINK_API int jaylink_emucom_write(struct jaylink_device_handle *devh, uint32_t channel, const uint8_t *buffer, uint32_t *length)
Write to an EMUCOM channel.
Definition: emucom.c:206
JAYLINK_PRIV void buffer_set_u32(uint8_t *buffer, uint32_t value, size_t offset)
Write a 32-bit unsigned integer value to a buffer.
Definition: buffer.c:95