summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base.c4
-rw-r--r--private.h16
-rw-r--r--reader.c34
3 files changed, 46 insertions, 8 deletions
diff --git a/base.c b/base.c
index 1355486..1adc185 100644
--- a/base.c
+++ b/base.c
@@ -351,6 +351,10 @@ int ipecamera_start(pcilib_context_t *vctx, pcilib_event_t event_mask, pcilib_ev
ctx->parse_data = (flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY)?0:1;
ctx->cur_size = 0;
+#ifdef IPECAMERA_BUG_MULTIFRAME_HEADERS
+ ctx->saved_header_size = 0;
+#endif /* IPECAMERA_BUG_MULTIFRAME_HEADERS */
+
switch (ctx->firmware) {
case IPECAMERA_FIRMWARE_UFO5:
ctx->dim.width = CMOSIS_WIDTH;
diff --git a/private.h b/private.h
index a0034c8..18138e7 100644
--- a/private.h
+++ b/private.h
@@ -20,6 +20,7 @@
#define IPECAMERA_BUG_MISSING_PAYLOAD //**< CMOSIS fails to provide a first payload for each frame, therefore the frame is 32 bit shorter */
#define IPECAMERA_BUG_MULTIFRAME_PACKETS //**< This is by design, start of packet comes directly after the end of last one in streaming mode */
+#define IPECAMERA_BUG_MULTIFRAME_HEADERS //**< UFO Camera operates with 32-byte entities, but some times there is 16-byte padding before the data which may result in spliting the header between 2 DMA packets. We still need to define a minimal number of bytes which are always in the same DMA packet (CMOSIS_ENTITY_SIZE) */
#define IPECAMERA_BUG_REPEATING_DATA //**< 16 bytes repeated at frame offset 4096, the problem start/stop happenning on board restart */
//#define IPECAMERA_BUG_INCOMPLETE_PACKETS //**< Support incomplete packets, i.e. check for frame magic even if full frame size is not reached yet (slow) */
//#define IPECAMERA_ANNOUNCE_READY //**< Announce new event only after the reconstruction is done */
@@ -46,8 +47,13 @@
#define IPECAMERA_END_OF_SEQUENCE 0x1F001001
-#define CMOSIS_FRAME_HEADER_SIZE 8 * sizeof(ipecamera_payload_t)
-#define CMOSIS_FRAME_TAIL_SIZE 8 * sizeof(ipecamera_payload_t)
+#define CMOSIS_FRAME_HEADER_SIZE (8 * sizeof(ipecamera_payload_t))
+#define CMOSIS_FRAME_TAIL_SIZE (8 * sizeof(ipecamera_payload_t))
+#ifdef IPECAMERA_BUG_MULTIFRAME_HEADERS
+# define CMOSIS_ENTITY_SIZE (4 * sizeof(ipecamera_payload_t)) //**< This normaly should be equal to 32 bytes like header and tail, but in fact is only 16 bytes */
+#else /* IPECAMERA_BUG_MULTIFRAME_HEADERS */
+# define CMOSIS_ENTITY_SIZE (8 * sizeof(ipecamera_payload_t)) //**< This normaly should be equal to 32 bytes like header and tail, but in fact is only 16 bytes */
+#endif /* IPECAMERA_BUG_MULTIFRAME_HEADERS */
#define CMOSIS_MAX_CHANNELS 16
#define CMOSIS_PIXELS_PER_CHANNEL 128
@@ -228,7 +234,11 @@ struct ipecamera_s {
void *buffer;
ipecamera_change_mask_t *cmask;
ipecamera_frame_t *frame;
-
+
+#ifdef IPECAMERA_BUG_MULTIFRAME_HEADERS
+ size_t saved_header_size; /**< If it happened that the frame header is split between 2 DMA packets, this variable holds the size of the part containing in the first packet */
+ char saved_header[CMOSIS_FRAME_HEADER_SIZE]; /**< If it happened that the frame header is split between 2 DMA packets, this variable holds the part containing in the first packet */
+#endif /* IPECAMERA_BUG_MULTIFRAME_HEADERS */
ipecamera_image_dimensions_t dim;
diff --git a/reader.c b/reader.c
index e293005..b603e47 100644
--- a/reader.c
+++ b/reader.c
@@ -163,13 +163,30 @@ static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t
ipecamera_debug_buffer(RAW_PACKETS, bufsize, buf, PCILIB_DEBUG_BUFFER_MKDIR, "frame%4lu/frame%9lu", ctx->event_id, packet_id);
if (!ctx->cur_size) {
+#ifdef IPECAMERA_BUG_MULTIFRAME_HEADERS
+ if (ctx->saved_header_size) {
+ void *buf2 = alloca(ctx->saved_header_size + bufsize);
+ if (!buf2) {
+ pcilib_error("Error allocating %zu bytes of memory in stack", ctx->saved_header_size + bufsize);
+ return -PCILIB_ERROR_MEMORY;
+ }
+ memcpy(buf2, ctx->saved_header, ctx->saved_header_size);
+ memcpy(buf2 + ctx->saved_header_size, buf, bufsize);
+
+ buf = buf2;
+ bufsize += ctx->saved_header_size;
+
+ ctx->saved_header_size = 0;
+ }
+#endif /* IPECAMERA_BUG_MULTIFRAME_HEADERS */
+
#if defined(IPECAMERA_BUG_INCOMPLETE_PACKETS)||defined(IPECAMERA_BUG_MULTIFRAME_PACKETS)
size_t startpos;
- for (startpos = 0; (startpos + CMOSIS_FRAME_HEADER_SIZE) <= bufsize; startpos += sizeof(ipecamera_payload_t)) {
+ for (startpos = 0; (startpos + CMOSIS_ENTITY_SIZE) <= bufsize; startpos += sizeof(ipecamera_payload_t)) {
if (!CHECK_FRAME_MAGIC(buf + startpos)) break;
}
- if ((startpos + CMOSIS_FRAME_HEADER_SIZE) > bufsize) {
+ if ((startpos + CMOSIS_ENTITY_SIZE) > bufsize) {
ipecamera_debug_buffer(RAW_PACKETS, bufsize, NULL, 0, "frame%4lu/frame%9lu.invalid", ctx->event_id, packet_id);
if (invalid_frame_id != ctx->event_id) {
@@ -200,8 +217,15 @@ static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t
// We should handle the case when multi-header is split between multiple DMA packets
if (!ipecamera_parse_header(ctx, buf, bufsize))
return PCILIB_STREAMING_CONTINUE;
+
+#ifdef IPECAMERA_BUG_MULTIFRAME_HEADERS
+ } else if ((bufsize >= CMOSIS_ENTITY_SIZE)&&(!CHECK_FRAME_MAGIC(buf))) {
+ memcpy(ctx->saved_header, buf, bufsize);
+ ctx->saved_header_size = bufsize;
+ return PCILIB_STREAMING_REQ_FRAGMENT;
+#endif /* IPECAMERA_BUG_MULTIFRAME_HEADERS */
} else {
- ipecamera_debug(HARDWARE, "Frame magic is not found, ignoring broken data...");
+ ipecamera_debug(HARDWARE, "Frame magic is not found in the remaining DMA packet consisting of %u bytes, ignoring broken data...", bufsize);
return PCILIB_STREAMING_CONTINUE;
}
}
@@ -213,11 +237,11 @@ static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t
if (ctx->cur_size + bufsize > ctx->roi_raw_size) {
size_t need;
- for (need = ctx->roi_raw_size - ctx->cur_size; (need + CMOSIS_FRAME_HEADER_SIZE) <= bufsize; need += sizeof(uint32_t)) {
+ for (need = ctx->roi_raw_size - ctx->cur_size; (need + CMOSIS_ENTITY_SIZE) <= bufsize; need += sizeof(uint32_t)) {
if (!CHECK_FRAME_MAGIC(buf + need)) break;
}
- if ((need + CMOSIS_FRAME_HEADER_SIZE) <= bufsize) {
+ if ((need + CMOSIS_ENTITY_SIZE) <= bufsize) {
extra_data = bufsize - need;
eof = 1;
}