3 * Unigraf DisplayPort AUX channel monitor output parser
4 * Copyright 2018, Dirk Eibach, Guntermann & Drunck GmbH <dirk.eibach@gdsys.cc>
6 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "file_wrappers.h"
19 DPA400_DATA_END
= 0x01,
23 DPA400_TS_OVERFLOW
= 0x84,
26 struct dpa400_header
{
35 static int dpa400_file_type_subtype
= -1;
37 void register_dpa400(void);
39 static bool dpa400_read_header(FILE_T fh
, struct dpa400_header
*hdr
, int *err
, char **err_info
)
41 if (!wtap_read_bytes_or_eof(fh
, hdr
, sizeof(struct dpa400_header
), err
, err_info
))
44 if (hdr
->sb0
|| hdr
->sb1
|| hdr
->sb2
) {
45 *err
= WTAP_ERR_BAD_FILE
;
46 *err_info
= g_strdup("dpa400: malformed packet header");
53 static void get_ts(struct dpa400_header
*hdr
, nstime_t
*ts
)
57 val
= (hdr
->t0
| (hdr
->t1
<< 8) | ((hdr
->t2
& 0x7f) << 16)) << 5;
59 ts
->secs
= val
/ 1000000;
60 ts
->nsecs
= (val
% 1000000) * 1000;
63 static void get_ts_overflow(nstime_t
*ts
)
65 uint32_t val
= 0x7fffff << 5;
67 ts
->secs
= val
/ 1000000;
68 ts
->nsecs
= (val
% 1000000) * 1000;
71 static uint8_t get_from(struct dpa400_header
*hdr
)
73 return hdr
->t2
& 0x80;
76 static bool dpa400_read_packet(wtap
*wth
, FILE_T fh
, wtap_rec
*rec
,
77 Buffer
*buf
, int *err
, char **err_info
)
82 if (!wth
|| !rec
|| !buf
)
85 if (!wtap_read_bytes_or_eof(fh
, chunk
, sizeof(chunk
), err
, err_info
))
89 *err
= WTAP_ERR_BAD_FILE
;
90 *err_info
= g_strdup("dpa400: malformed packet framing");
96 ws_buffer_append(buf
, &chunk
[0], 1);
101 struct dpa400_header hdr
;
103 if (!dpa400_read_header(fh
, &hdr
, err
, err_info
))
106 get_ts(&hdr
, &rec
->ts
);
108 rec
->rec_type
= REC_TYPE_PACKET
;
109 rec
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
110 rec
->presence_flags
= WTAP_HAS_TS
;
111 rec
->rec_header
.packet_header
.caplen
= rec
->rec_header
.packet_header
.len
= 0;
118 struct dpa400_header hdr
;
120 if (!dpa400_read_header(fh
, &hdr
, err
, err_info
))
123 get_ts(&hdr
, &rec
->ts
);
125 if (!wtap_read_bytes_or_eof(fh
, chunk
, sizeof(chunk
), err
, err_info
))
129 *err
= WTAP_ERR_BAD_FILE
;
130 *err_info
= g_strdup("dpa400: malformed packet");
134 ws_buffer_append(buf
, &chunk
[0], 1);
137 rec
->rec_type
= REC_TYPE_PACKET
;
138 rec
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
139 rec
->presence_flags
= WTAP_HAS_TS
;
140 rec
->rec_header
.packet_header
.caplen
= rec
->rec_header
.packet_header
.len
= ctr
;
146 struct dpa400_header hdr
;
149 if (!dpa400_read_header(fh
, &hdr
, err
, err_info
))
152 get_ts(&hdr
, &rec
->ts
);
154 from_source
= !get_from(&hdr
);
155 ws_buffer_append(buf
, &from_source
, 1);
159 if (!wtap_read_bytes_or_eof(fh
, chunk
, sizeof(chunk
), err
, err_info
))
165 if (++ctr
> WTAP_MAX_PACKET_SIZE_STANDARD
) {
166 *err
= WTAP_ERR_BAD_FILE
;
167 *err_info
= ws_strdup_printf("dpa400: File has data record bigger than maximum of %u",
168 WTAP_MAX_PACKET_SIZE_STANDARD
);
172 ws_buffer_append(buf
, &chunk
[0], 1);
175 rec
->rec_type
= REC_TYPE_PACKET
;
176 rec
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
177 rec
->presence_flags
= WTAP_HAS_TS
;
178 rec
->rec_header
.packet_header
.caplen
= rec
->rec_header
.packet_header
.len
= ctr
;
183 case DPA400_TS_OVERFLOW
: {
184 get_ts_overflow(&rec
->ts
);
186 rec
->rec_type
= REC_TYPE_PACKET
;
187 rec
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
188 rec
->presence_flags
= WTAP_HAS_TS
;
189 rec
->rec_header
.packet_header
.caplen
= rec
->rec_header
.packet_header
.len
= ctr
;
195 *err
= WTAP_ERR_BAD_FILE
;
196 *err_info
= ws_strdup_printf("dpa400: unknown packet type %02x", chunk
[0]);
203 static bool dpa400_seek_read(wtap
*wth
,int64_t seek_off
, wtap_rec
*rec
, Buffer
*buf
,
204 int *err
, char **err_info
)
206 if (file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) == -1)
209 return dpa400_read_packet(wth
, wth
->random_fh
, rec
, buf
, err
, err_info
);
212 static bool dpa400_read(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
,
213 int *err
, char **err_info
, int64_t *data_offset
)
215 *data_offset
= file_tell(wth
->fh
);
217 return dpa400_read_packet(wth
, wth
->fh
, rec
, buf
, err
, err_info
);
220 wtap_open_return_val
dpa400_open(wtap
*wth
, int *err
, char **err_info
)
223 const char dpa_magic
[] = { 'D', 'B', 'F', 'R' };
225 /* Read in the number that should be at the start of a "dpa-400" file */
226 if (!wtap_read_bytes(wth
->fh
, &magic
, sizeof magic
, err
, err_info
)) {
227 if (*err
!= WTAP_ERR_SHORT_READ
)
228 return WTAP_OPEN_ERROR
;
229 return WTAP_OPEN_NOT_MINE
;
232 if (memcmp(magic
, dpa_magic
, sizeof(dpa_magic
)))
233 return WTAP_OPEN_NOT_MINE
;
235 wth
->file_type_subtype
= dpa400_file_type_subtype
;
236 wth
->file_encap
= WTAP_ENCAP_DPAUXMON
;
237 wth
->file_tsprec
= WTAP_TSPREC_USEC
;
238 wth
->subtype_read
= dpa400_read
;
239 wth
->subtype_seek_read
= dpa400_seek_read
;
240 wth
->snapshot_length
= 0;
243 * Add an IDB; we don't know how many interfaces were
244 * involved, so we just say one interface, about which
245 * we only know the link-layer type, snapshot length,
246 * and time stamp resolution.
248 wtap_add_generated_idb(wth
);
250 return WTAP_OPEN_MINE
;
253 static const struct supported_block_type dpa400_blocks_supported
[] = {
255 * We support packet blocks, with no comments or other options.
257 { WTAP_BLOCK_PACKET
, MULTIPLE_BLOCKS_SUPPORTED
, NO_OPTIONS_SUPPORTED
}
260 static const struct file_type_subtype_info dpa400_info
= {
261 "Unigraf DPA-400 capture", "dpa400", "bin", NULL
,
262 false, BLOCKS_SUPPORTED(dpa400_blocks_supported
),
266 void register_dpa400(void)
268 dpa400_file_type_subtype
= wtap_register_file_type_subtype(&dpa400_info
);
271 * Register name for backwards compatibility with the
272 * wtap_filetypes table in Lua.
274 wtap_register_backwards_compatibility_lua_name("DPA400",
275 dpa400_file_type_subtype
);
279 * Editor modelines - https://www.wireshark.org/tools/modelines.html
284 * indent-tabs-mode: t
287 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
288 * :indentSize=8:tabSize=8:noTabs=false: