diff options
author | Thies Moeller <thies.moeller@baslerweb.com> | 2016-02-19 15:33:15 +0000 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2016-02-25 04:39:12 +0000 |
commit | 03dfd9cead43930e481fad614ac83e760cee98ea (patch) | |
tree | 7535f503abb36756779c6bdb552970b06d068e0f /epan | |
parent | 3ada3c0865ecd51e1c59cfec81f9f4c67d74a920 (diff) |
u3v: dissector for the USB3 Vision protocol
Dissector for the USB3 Vision machine vision camera protocol.
* Descriptors
* Bootstrap registers
* Control (GenCP)
* Stream data
A sample capture (usb_u3v_sample.pcapng) has been uploaded to
https://wiki.wireshark.org/SampleCapture
USB3 Vision a standard developed under the sponsorship
of the AIA for the benefit of the machine vision industry.
U3V stands for USB3 Vision (TM) Protocol
Change-Id: If1206df7974c6a91cf18f59ddecf9d38b9827934
Reviewed-on: https://code.wireshark.org/review/14008
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan')
-rw-r--r-- | epan/CMakeLists.txt | 1 | ||||
-rw-r--r-- | epan/dissectors/Makefile.common | 1 | ||||
-rw-r--r-- | epan/dissectors/packet-u3v.c | 2755 |
3 files changed, 2757 insertions, 0 deletions
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt index b2d2ef008c..6b15f30ec3 100644 --- a/epan/CMakeLists.txt +++ b/epan/CMakeLists.txt @@ -1362,6 +1362,7 @@ set(DISSECTOR_SRC dissectors/packet-turnchannel.c dissectors/packet-tuxedo.c dissectors/packet-tzsp.c + dissectors/packet-u3v.c dissectors/packet-ua.c dissectors/packet-ua3g.c dissectors/packet-uasip.c diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index 662aff3d52..de4cd27864 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -1279,6 +1279,7 @@ DISSECTOR_SRC = \ packet-turnchannel.c \ packet-tuxedo.c \ packet-tzsp.c \ + packet-u3v.c \ packet-ua.c \ packet-ua3g.c \ packet-uasip.c \ diff --git a/epan/dissectors/packet-u3v.c b/epan/dissectors/packet-u3v.c new file mode 100644 index 0000000000..7bf2df2ff0 --- /dev/null +++ b/epan/dissectors/packet-u3v.c @@ -0,0 +1,2755 @@ +/* packet-u3v.c +* Routines for AIA USB3 Vision (TM) Protocol dissection +* Copyright 2016, AIA (www.visiononline.org) +* +* USB3 Vision (TM): USB3 Vision a standard developed under the sponsorship of +* the AIA for the benefit of the machine vision industry. +* U3V stands for USB3 Vision (TM) Protocol. +* +* Wireshark - Network traffic analyzer +* By Gerald Combs <gerald@wireshark.org> +* Copyright 1998 Gerald Combs +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "config.h" + +#include <epan/packet.h> +#include <epan/proto_data.h> +#include <epan/dissectors/packet-usb.h> + + + +/* +U3V descriptor constants +*/ +#define DESCRIPTOR_TYPE_U3V_INTERFACE 0x24 +#define DESCRIPTOR_SUBTYPE_U3V_DEVICE_INFO 0x01 + +/* + Bootstrap registers addresses + */ +#define U3V_ABRM_GENCP_VERSION 0x00000000 +#define U3V_ABRM_MANUFACTURER_NAME 0x00000004 +#define U3V_ABRM_MODEL_NAME 0x00000044 +#define U3V_ABRM_FAMILY_NAME 0x00000084 +#define U3V_ABRM_DEVICE_VERSION 0x000000C4 +#define U3V_ABRM_MANUFACTURER_INFO 0x00000104 +#define U3V_ABRM_SERIAL_NUMBER 0x00000144 +#define U3V_ABRM_USER_DEFINED_NAME 0x00000184 +#define U3V_ABRM_DEVICE_CAPABILITY 0x000001C4 +#define U3V_ABRM_MAXIMUM_DEVICE_RESPONSE_TIME 0x000001CC +#define U3V_ABRM_MANIFEST_TABLE_ADDRESS 0x000001D0 +#define U3V_ABRM_SBRM_ADDRESS 0x000001D8 +#define U3V_ABRM_DEVICE_CONFIGURATION 0x000001E0 +#define U3V_ABRM_HEARTBEAT_TIMEOUT 0x000001E8 +#define U3V_ABRM_MESSAGE_CHANNEL_CHANNEL_ID 0x000001EC +#define U3V_ABRM_TIMESTAMP 0x000001F0 +#define U3V_ABRM_TIMESTAMP_LATCH 0x000001F8 +#define U3V_ABRM_TIMESTAMP_INCREMENT 0x000001FC +#define U3V_ABRM_ACCESS_PRIVILEGE 0x00000204 +#define U3V_ABRM_PROTOCOL_ENDIANESS 0x00000208 +#define U3V_ABRM_IMPLEMENTATION_ENDIANESS 0x0000020C +#define U3V_SBRM_U3V_VERSION 0x00000000 +#define U3V_SBRM_U3VCP_CAPABILITY_REGISTER 0x00000004 +#define U3V_SBRM_U3VCP_CONFIGURATION_REGISTER 0x0000000C +#define U3V_SBRM_MAXIMUM_COMMAND_TRANSFER_LENGTH 0x00000014 +#define U3V_SBRM_MAXIMUM_ACKNOWLEDGE_TRANSFER_LENGTH 0x00000018 +#define U3V_SBRM_NUMBER_OF_STREAM_CHANNELS 0x0000001C +#define U3V_SBRM_SIRM_ADDRESS 0x00000020 +#define U3V_SBRM_SIRM_LENGTH 0x00000028 +#define U3V_SBRM_EIRM_ADDRESS 0x0000002C +#define U3V_SBRM_EIRM_LENGTH 0x00000034 +#define U3V_SBRM_IIDC2_ADDRESS 0x00000038 +#define U3V_SBRM_CURRENT_SPEED 0x00000040 +#define U3V_SIRM_SI_INFO 0x00000000 +#define U3V_SIRM_SI_CONTROL 0x00000004 +#define U3V_SIRM_SI_REQUIRED_PAYLOAD_SIZE 0x00000008 +#define U3V_SIRM_SI_REQUIRED_LEADER_SIZE 0x00000010 +#define U3V_SIRM_SI_REQUIRED_TRAILER_SIZE 0x00000014 +#define U3V_SIRM_SI_MAXIMUM_LEADER_SIZE 0x00000018 +#define U3V_SIRM_SI_PAYLOAD_TRANSFER_SIZE 0x0000001C +#define U3V_SIRM_SI_PAYLOAD_TRANSFER_COUNT 0x00000020 +#define U3V_SIRM_SI_PAYLOAD_FINAL_TRANSFER1_SIZE 0x00000024 +#define U3V_SIRM_SI_PAYLOAD_FINAL_TRANSFER2_SIZE 0x00000028 +#define U3V_SIRM_SI_MAXIMUM_TRAILER_SIZE 0x0000002C +#define U3V_EIRM_EI_CONTROL 0x00000000 +#define U3V_EIRM_MAXIMUM_EVENT_TRANSFER_LENGTH 0x00000004 +#define U3V_EIRM_EVENT_TEST_CONTROL 0x00000008 + +/* + Command and acknowledge IDs +*/ +#define U3V_READMEM_CMD 0x0800 +#define U3V_READMEM_ACK 0x0801 +#define U3V_WRITEMEM_CMD 0x0802 +#define U3V_WRITEMEM_ACK 0x0803 +#define U3V_PENDING_ACK 0x0805 +#define U3V_EVENT_CMD 0x0C00 +#define U3V_EVENT_ACK 0x0C01 + +/* + Status codes +*/ +#define U3V_STATUS_GENCP_SUCCESS 0x0000 +#define U3V_STATUS_GENCP_NOT_IMPLEMENTED 0x8001 +#define U3V_STATUS_GENCP_INVALID_PARAMETER 0x8002 +#define U3V_STATUS_GENCP_INVALID_ADDRESS 0x8003 +#define U3V_STATUS_GENCP_WRITE_PROTECT 0x8004 +#define U3V_STATUS_GENCP_BAD_ALIGNMENT 0x8005 +#define U3V_STATUS_GENCP_ACCESS_DENIED 0x8006 +#define U3V_STATUS_GENCP_BUSY 0x8007 +/* 0x8008 - 0x800A have been used in GEV 1.x but are now deprecated. The GenCP specification did NOT recycle these values! */ +#define U3V_STATUS_GENCP_MSG_TIMEOUT 0x800B +/* 0x800C - 0x800D are used in GEV only. The GenCP specification did NOT recycle these values! */ +#define U3V_STATUS_GENCP_INVALID_HEADER 0x800E +#define U3V_STATUS_GENCP_WRONG_CONFIG 0x800F + +#define U3V_STATUS_GENCP_ERROR 0x8FFF + +#define U3V_STATUS_RESEND_NOT_SUPPORTED 0xA001 +#define U3V_STATUS_DSI_ENDPOINT_HALTED 0xA002 +#define U3V_STATUS_SI_PAYLOAD_SIZE_NOT_ALIGNED 0xA003 +#define U3V_STATUS_SI_REGISTERS_INCONSISTENT 0xA004 +#define U3V_STATUS_DATA_DISCARDED 0xA100 + +/* + Prefix +*/ +#define U3V_CONTROL_PREFIX 0x43563355 +#define U3V_EVENT_PREFIX 0x45563355 + +#define U3V_STREAM_LEADER_PREFIX 0x4C563355 +#define U3V_STREAM_TRAILER_PREFIX 0x54563355 + +/* + Event IDs +*/ +#define U3V_EVENT_TESTEVENT 0x4FFF + +/* + * Pixel Format IDs +*/ +#define PFNC_U3V_MONO8 0x01080001 +#define PFNC_U3V_MONO8S 0x01080002 +#define PFNC_U3V_MONO10 0x01100003 +#define PFNC_U3V_MONO10PACKED 0x010C0004 +#define PFNC_U3V_MONO12 0x01100005 +#define PFNC_U3V_MONO12PACKED 0x010C0006 +#define PFNC_U3V_MONO16 0x01100007 +#define PFNC_U3V_BAYERGR8 0x01080008 +#define PFNC_U3V_BAYERRG8 0x01080009 +#define PFNC_U3V_BAYERGB8 0x0108000A +#define PFNC_U3V_BAYERBG8 0x0108000B +#define PFNC_U3V_BAYERGR10 0x0110000C +#define PFNC_U3V_BAYERRG10 0x0110000D +#define PFNC_U3V_BAYERGB10 0x0110000E +#define PFNC_U3V_BAYERBG10 0x0110000F +#define PFNC_U3V_BAYERGR12 0x01100010 +#define PFNC_U3V_BAYERRG12 0x01100011 +#define PFNC_U3V_BAYERGB12 0x01100012 +#define PFNC_U3V_BAYERBG12 0x01100013 +#define PFNC_U3V_RGB8 0x02180014 +#define PFNC_U3V_BGR8 0x02180015 +#define PFNC_U3V_RGBA8 0x02200016 +#define PFNC_U3V_BGRA8 0x02200017 +#define PFNC_U3V_RGB10 0x02300018 +#define PFNC_U3V_BGR10 0x02300019 +#define PFNC_U3V_RGB12 0x0230001A +#define PFNC_U3V_BGR12 0x0230001B +#define PFNC_U3V_RGB10V1PACKED 0x0220001C +#define PFNC_U3V_RGB10P32 0x0220001D +#define PFNC_U3V_YUV411_8_UYYVYY 0x020C001E +#define PFNC_U3V_YUV422_8_UYVY 0x0210001F +#define PFNC_U3V_YUV8_UYV 0x02180020 +#define PFNC_U3V_RGB8_PLANAR 0x02180021 +#define PFNC_U3V_RGB10_PLANAR 0x02300022 +#define PFNC_U3V_RGB12_PLANAR 0x02300023 +#define PFNC_U3V_RGB16_PLANAR 0x02300024 +#define PFNC_U3V_MONO14 0x01100025 +#define PFNC_U3V_BAYERGR10PACKED 0x010C0026 +#define PFNC_U3V_BAYERRG10PACKED 0x010C0027 +#define PFNC_U3V_BAYERGB10PACKED 0x010C0028 +#define PFNC_U3V_BAYERBG10PACKED 0x010C0029 +#define PFNC_U3V_BAYERGR12PACKED 0x010C002A +#define PFNC_U3V_BAYERRG12PACKED 0x010C002B +#define PFNC_U3V_BAYERGB12PACKED 0x010C002C +#define PFNC_U3V_BAYERBG12PACKED 0x010C002D +#define PFNC_U3V_BAYERGR16 0x0110002E +#define PFNC_U3V_BAYERRG16 0x0110002F +#define PFNC_U3V_BAYERGB16 0x01100030 +#define PFNC_U3V_BAYERBG16 0x01100031 +#define PFNC_U3V_YUV422_8 0x02100032 +#define PFNC_U3V_RGB16 0x02300033 +#define PFNC_U3V_RGB12V1PACKED 0x02240034 +#define PFNC_U3V_RGB565P 0x02100035 +#define PFNC_U3V_BGR565P 0x02100036 +#define PFNC_U3V_MONO1P 0x01010037 +#define PFNC_U3V_MONO2P 0x01020038 +#define PFNC_U3V_MONO4P 0x01040039 +#define PFNC_U3V_YCBCR8_CBYCR 0x0218003A +#define PFNC_U3V_YCBCR422_8 0x0210003B +#define PFNC_U3V_YCBCR411_8_CBYYCRYY 0x020C003C +#define PFNC_U3V_YCBCR601_8_CBYCR 0x0218003D +#define PFNC_U3V_YCBCR601_422_8 0x0210003E +#define PFNC_U3V_YCBCR601_411_8_CBYYCRYY 0x020C003F +#define PFNC_U3V_YCBCR709_8_CBYCR 0x02180040 +#define PFNC_U3V_YCBCR709_422_8 0x02100041 +#define PFNC_U3V_YCBCR709_411_8_CBYYCRYY 0x020C0042 +#define PFNC_U3V_YCBCR422_8_CBYCRY 0x02100043 +#define PFNC_U3V_YCBCR601_422_8_CBYCRY 0x02100044 +#define PFNC_U3V_YCBCR709_422_8_CBYCRY 0x02100045 +#define PFNC_U3V_MONO10P 0x010A0046 +#define PFNC_U3V_MONO12P 0x010C0047 +#define PFNC_U3V_BGR10P 0x021E0048 +#define PFNC_U3V_BGR12P 0x02240049 +#define PFNC_U3V_BGR14 0x0230004A +#define PFNC_U3V_BGR16 0x0230004B +#define PFNC_U3V_BGRA10 0x0240004C +#define PFNC_U3V_BGRA10P 0x0228004D +#define PFNC_U3V_BGRA12 0x0240004E +#define PFNC_U3V_BGRA12P 0x0230004F +#define PFNC_U3V_BGRA14 0x02400050 +#define PFNC_U3V_BGRA16 0x02400051 +#define PFNC_U3V_BAYERBG10P 0x010A0052 +#define PFNC_U3V_BAYERBG12P 0x010C0053 +#define PFNC_U3V_BAYERGB10P 0x010A0054 +#define PFNC_U3V_BAYERGB12P 0x010C0055 +#define PFNC_U3V_BAYERGR10P 0x010A0056 +#define PFNC_U3V_BAYERGR12P 0x010C0057 +#define PFNC_U3V_BAYERRG10P 0x010A0058 +#define PFNC_U3V_BAYERRG12P 0x010C0059 +#define PFNC_U3V_YCBCR411_8 0x020C005A +#define PFNC_U3V_YCBCR8 0x0218005B +#define PFNC_U3V_RGB10P 0x021E005C +#define PFNC_U3V_RGB12P 0x0224005D +#define PFNC_U3V_RGB14 0x0230005E +#define PFNC_U3V_RGBA10 0x0240005F +#define PFNC_U3V_RGBA10P 0x02280060 +#define PFNC_U3V_RGBA12 0x02400061 +#define PFNC_U3V_RGBA12P 0x02300062 +#define PFNC_U3V_RGBA14 0x02400063 +#define PFNC_U3V_RGBA16 0x02400064 +#define PFNC_U3V_YCBCR422_10 0x02200065 +#define PFNC_U3V_YCBCR422_12 0x02200066 +#define PFNC_U3V_SCF1WBWG8 0x01080067 +#define PFNC_U3V_SCF1WBWG10 0x01100068 +#define PFNC_U3V_SCF1WBWG10P 0x010A0069 +#define PFNC_U3V_SCF1WBWG12 0x0110006A +#define PFNC_U3V_SCF1WBWG12P 0x010C006B +#define PFNC_U3V_SCF1WBWG14 0x0110006C +#define PFNC_U3V_SCF1WBWG16 0x0110006D +#define PFNC_U3V_SCF1WGWB8 0x0108006E +#define PFNC_U3V_SCF1WGWB10 0x0110006F +#define PFNC_U3V_SCF1WGWB10P 0x010A0070 +#define PFNC_U3V_SCF1WGWB12 0x01100071 +#define PFNC_U3V_SCF1WGWB12P 0x010C0072 +#define PFNC_U3V_SCF1WGWB14 0x01100073 +#define PFNC_U3V_SCF1WGWB16 0x01100074 +#define PFNC_U3V_SCF1WGWR8 0x01080075 +#define PFNC_U3V_SCF1WGWR10 0x01100076 +#define PFNC_U3V_SCF1WGWR10P 0x010A0077 +#define PFNC_U3V_SCF1WGWR12 0x01100078 +#define PFNC_U3V_SCF1WGWR12P 0x010C0079 +#define PFNC_U3V_SCF1WGWR14 0x0110007A +#define PFNC_U3V_SCF1WGWR16 0x0110007B +#define PFNC_U3V_SCF1WRWG8 0x0108007C +#define PFNC_U3V_SCF1WRWG10 0x0110007D +#define PFNC_U3V_SCF1WRWG10P 0x010A007E +#define PFNC_U3V_SCF1WRWG12 0x0110007F +#define PFNC_U3V_SCF1WRWG12P 0x010C0080 +#define PFNC_U3V_SCF1WRWG14 0x01100081 +#define PFNC_U3V_SCF1WRWG16 0x01100082 +#define PFNC_U3V_YCBCR10_CBYCR 0x02300083 +#define PFNC_U3V_YCBCR10P_CBYCR 0x021E0084 +#define PFNC_U3V_YCBCR12_CBYCR 0x02300085 +#define PFNC_U3V_YCBCR12P_CBYCR 0x02240086 +#define PFNC_U3V_YCBCR422_10P 0x02140087 +#define PFNC_U3V_YCBCR422_12P 0x02180088 +#define PFNC_U3V_YCBCR601_10_CBYCR 0x02300089 +#define PFNC_U3V_YCBCR601_10P_CBYCR 0x021E008A +#define PFNC_U3V_YCBCR601_12_CBYCR 0x0230008B +#define PFNC_U3V_YCBCR601_12P_CBYCR 0x0224008C +#define PFNC_U3V_YCBCR601_422_10 0x0220008D +#define PFNC_U3V_YCBCR601_422_10P 0x0214008E +#define PFNC_U3V_YCBCR601_422_12 0x0220008F +#define PFNC_U3V_YCBCR601_422_12P 0x02180090 +#define PFNC_U3V_YCBCR709_10_CBYCR 0x02300091 +#define PFNC_U3V_YCBCR709_10P_CBYCR 0x021E0092 +#define PFNC_U3V_YCBCR709_12_CBYCR 0x02300093 +#define PFNC_U3V_YCBCR709_12P_CBYCR 0x02240094 +#define PFNC_U3V_YCBCR709_422_10 0x02200095 +#define PFNC_U3V_YCBCR709_422_10P 0x02140096 +#define PFNC_U3V_YCBCR709_422_12 0x02200097 +#define PFNC_U3V_YCBCR709_422_12P 0x02180098 +#define PFNC_U3V_YCBCR422_10_CBYCRY 0x02200099 +#define PFNC_U3V_YCBCR422_10P_CBYCRY 0x0214009A +#define PFNC_U3V_YCBCR422_12_CBYCRY 0x0220009B +#define PFNC_U3V_YCBCR422_12P_CBYCRY 0x0218009C +#define PFNC_U3V_YCBCR601_422_10_CBYCRY 0x0220009D +#define PFNC_U3V_YCBCR601_422_10P_CBYCRY 0x0214009E +#define PFNC_U3V_YCBCR601_422_12_CBYCRY 0x0220009F +#define PFNC_U3V_YCBCR601_422_12P_CBYCRY 0x021800A0 +#define PFNC_U3V_YCBCR709_422_10_CBYCRY 0x022000A1 +#define PFNC_U3V_YCBCR709_422_10P_CBYCRY 0x021400A2 +#define PFNC_U3V_YCBCR709_422_12_CBYCRY 0x022000A3 +#define PFNC_U3V_YCBCR709_422_12P_CBYCRY 0x021800A4 +#define PFNC_U3V_BICOLORRGBG8 0x021000A5 +#define PFNC_U3V_BICOLORBGRG8 0x021000A6 +#define PFNC_U3V_BICOLORRGBG10 0x022000A7 +#define PFNC_U3V_BICOLORRGBG10P 0x021400A8 +#define PFNC_U3V_BICOLORBGRG10 0x022000A9 +#define PFNC_U3V_BICOLORBGRG10P 0x021400AA +#define PFNC_U3V_BICOLORRGBG12 0x022000AB +#define PFNC_U3V_BICOLORRGBG12P 0x021800AC +#define PFNC_U3V_BICOLORBGRG12 0x022000AD +#define PFNC_U3V_BICOLORBGRG12P 0x021800AE +#define PFNC_U3V_COORD3D_A8 0x010800AF +#define PFNC_U3V_COORD3D_B8 0x010800B0 +#define PFNC_U3V_COORD3D_C8 0x010800B1 +#define PFNC_U3V_COORD3D_ABC8 0x021800B2 +#define PFNC_U3V_COORD3D_ABC8_PLANAR 0x021800B3 +#define PFNC_U3V_COORD3D_AC8 0x021000B4 +#define PFNC_U3V_COORD3D_AC8_PLANAR 0x021000B5 +#define PFNC_U3V_COORD3D_A16 0x011000B6 +#define PFNC_U3V_COORD3D_B16 0x011000B7 +#define PFNC_U3V_COORD3D_C16 0x011000B8 +#define PFNC_U3V_COORD3D_ABC16 0x023000B9 +#define PFNC_U3V_COORD3D_ABC16_PLANAR 0x023000BA +#define PFNC_U3V_COORD3D_AC16 0x022000BB +#define PFNC_U3V_COORD3D_AC16_PLANAR 0x022000BC +#define PFNC_U3V_COORD3D_A32F 0x012000BD +#define PFNC_U3V_COORD3D_B32F 0x012000BE +#define PFNC_U3V_COORD3D_C32F 0x012000BF +#define PFNC_U3V_COORD3D_ABC32F 0x026000C0 +#define PFNC_U3V_COORD3D_ABC32F_PLANAR 0x026000C1 +#define PFNC_U3V_COORD3D_AC32F 0x024000C2 +#define PFNC_U3V_COORD3D_AC32F_PLANAR 0x024000C3 +#define PFNC_U3V_CONFIDENCE1 0x010800C4 +#define PFNC_U3V_CONFIDENCE1P 0x010100C5 +#define PFNC_U3V_CONFIDENCE8 0x010800C6 +#define PFNC_U3V_CONFIDENCE16 0x011000C7 +#define PFNC_U3V_CONFIDENCE32F 0x012000C8 +#define PFNC_U3V_R8 0x010800C9 +#define PFNC_U3V_R10 0x010A00CA +#define PFNC_U3V_R12 0x010C00CB +#define PFNC_U3V_R16 0x011000CC +#define PFNC_U3V_G8 0x010800CD +#define PFNC_U3V_G10 0x010A00CE +#define PFNC_U3V_G12 0x010C00CF +#define PFNC_U3V_G16 0x011000D0 +#define PFNC_U3V_B8 0x010800D1 +#define PFNC_U3V_B10 0x010A00D2 +#define PFNC_U3V_B12 0x010C00D3 +#define PFNC_U3V_B16 0x011000D4 +#define PFNC_U3V_COORD3D_A10P 0x010A00D5 +#define PFNC_U3V_COORD3D_B10P 0x010A00D6 +#define PFNC_U3V_COORD3D_C10P 0x010A00D7 +#define PFNC_U3V_COORD3D_A12P 0x010C00D8 +#define PFNC_U3V_COORD3D_B12P 0x010C00D9 +#define PFNC_U3V_COORD3D_C12P 0x010C00DA +#define PFNC_U3V_COORD3D_ABC10P 0x021E00DB +#define PFNC_U3V_COORD3D_ABC10P_PLANAR 0x021E00DC +#define PFNC_U3V_COORD3D_ABC12P 0x022400DE +#define PFNC_U3V_COORD3D_ABC12P_PLANAR 0x022400DF +#define PFNC_U3V_COORD3D_AC10P 0x021400F0 +#define PFNC_U3V_COORD3D_AC10P_PLANAR 0x021400F1 +#define PFNC_U3V_COORD3D_AC12P 0x021800F2 +#define PFNC_U3V_COORD3D_AC12P_PLANAR 0x021800F3 + +/* + Payload Types +*/ +#define U3V_STREAM_PAYLOAD_IMAGE 0x0001 +#define U3V_STREAM_PAYLOAD_IMAGE_EXT_CHUNK 0x4001 +#define U3V_STREAM_PAYLOAD_CHUNK 0x4000 + +void proto_register_u3v(void); +void proto_reg_handoff_u3v(void); + +/* Define the u3v protocol */ +static int proto_u3v = -1; + +/* GenCP transaction tracking + * the protocol only allows strict sequential + * communication. + * + * we track the current cmd/ack/pend_ack information + * in a struct that is created per GenCP communication + * + * in each request/response packet we add pointers + * to this information, that allow navigation between packets + * and dissection of addresses + */ +typedef struct _gencp_transaction_t { + guint32 cmd_frame; + guint32 ack_frame; + nstime_t cmd_time; + /* list of pending acknowledges */ + wmem_array_t *pend_ack_frame_list; + /* current requested address */ + guint64 address; + /* current requested count read/write */ + guint32 count; +} gencp_transaction_t; + +typedef struct _u3v_conv_info_t { + guint64 abrm_addr; + guint64 sbrm_addr; + guint64 sirm_addr; + guint64 eirm_addr; + guint64 iidc2_addr; + guint64 manifest_addr; + guint32 ep_stream; + gencp_transaction_t *trans_info; +} u3v_conv_info_t; + +/* + \brief IDs used for bootstrap dissection +*/ +static int hf_u3v_gencp_prefix = -1; +static int hf_u3v_flag = -1; +static int hf_u3v_acknowledge_required_flag = -1; +static int hf_u3v_command_id = -1; +static int hf_u3v_length = -1; +static int hf_u3v_request_id = -1; +static int hf_u3v_status = -1; +static int hf_u3v_address = -1; +static int hf_u3v_count = -1; +static int hf_u3v_eventcmd_id = -1; +static int hf_u3v_eventcmd_error_id = -1; +static int hf_u3v_eventcmd_device_specific_id = -1; +static int hf_u3v_eventcmd_timestamp = -1; +static int hf_u3v_eventcmd_data = -1; +static int hf_u3v_time_to_completion = -1; +static int hf_u3v_payloaddata = -1; +static int hf_u3v_reserved = -1; + +static int hf_u3v_bootstrap_GenCP_Version = -1; +static int hf_u3v_bootstrap_Manufacturer_Name = -1; +static int hf_u3v_bootstrap_Model_Name = -1; +static int hf_u3v_bootstrap_Family_Name = -1; +static int hf_u3v_bootstrap_Device_Version = -1; +static int hf_u3v_bootstrap_Manufacturer_Info = -1; +static int hf_u3v_bootstrap_Serial_Number = -1; +static int hf_u3v_bootstrap_User_Defined_Name = -1; +static int hf_u3v_bootstrap_Device_Capability = -1; +static int hf_u3v_bootstrap_Maximum_Device_Response_Time = -1; +static int hf_u3v_bootstrap_Manifest_Table_Address = -1; +static int hf_u3v_bootstrap_SBRM_Address = -1; +static int hf_u3v_bootstrap_Device_Configuration = -1; +static int hf_u3v_bootstrap_Heartbeat_Timeout = -1; +static int hf_u3v_bootstrap_Message_Channel_channel_id = -1; +static int hf_u3v_bootstrap_Timestamp = -1; +static int hf_u3v_bootstrap_Timestamp_Latch = -1; +static int hf_u3v_bootstrap_Timestamp_Increment = -1; +static int hf_u3v_bootstrap_Access_Privilege = -1; +static int hf_u3v_bootstrap_Protocol_Endianess = -1; +static int hf_u3v_bootstrap_Implementation_Endianess = -1; +static int hf_u3v_bootstrap_U3V_Version = -1; +static int hf_u3v_bootstrap_U3VCP_Capability_Register = -1; +static int hf_u3v_bootstrap_U3VCP_Configuration_Register = -1; +static int hf_u3v_bootstrap_Maximum_Command_Transfer_Length = -1; +static int hf_u3v_bootstrap_Maximum_Acknowledge_Transfer_Length = -1; +static int hf_u3v_bootstrap_Number_of_Stream_Channels = -1; +static int hf_u3v_bootstrap_SIRM_Address = -1; +static int hf_u3v_bootstrap_SIRM_Length = -1; +static int hf_u3v_bootstrap_EIRM_Address = -1; +static int hf_u3v_bootstrap_EIRM_Length = -1; +static int hf_u3v_bootstrap_IIDC2_Address = -1; +static int hf_u3v_bootstrap_Current_Speed = -1; +static int hf_u3v_bootstrap_SI_Info = -1; +static int hf_u3v_bootstrap_SI_Control = -1; +static int hf_u3v_bootstrap_SI_Required_Payload_Size = -1; +static int hf_u3v_bootstrap_SI_Required_Leader_Size = -1; +static int hf_u3v_bootstrap_SI_Required_Trailer_Size = -1; +static int hf_u3v_bootstrap_SI_Maximum_Leader_Size = -1; +static int hf_u3v_bootstrap_SI_Payload_Transfer_Size = -1; +static int hf_u3v_bootstrap_SI_Payload_Transfer_Count = -1; +static int hf_u3v_bootstrap_SI_Payload_Final_Transfer1_Size = -1; +static int hf_u3v_bootstrap_SI_Payload_Final_Transfer2_Size = -1; +static int hf_u3v_bootstrap_SI_Maximum_Trailer_Size = -1; +static int hf_u3v_bootstrap_EI_Control = -1; +static int hf_u3v_bootstrap_Maximum_Event_Transfer_Length = -1; +static int hf_u3v_bootstrap_Event_Test_Control = -1; +static int hf_u3v_custom_memory_addr = -1; +static int hf_u3v_custom_memory_data = -1; + +static int hf_u3v_scd_readmem_cmd = -1; +static int hf_u3v_scd_writemem_cmd = -1; +static int hf_u3v_scd_event_cmd = -1; +static int hf_u3v_scd_ack_readmem_ack = -1; +static int hf_u3v_scd_writemem_ack = -1; +static int hf_u3v_ccd_pending_ack = -1; +static int hf_u3v_stream_leader = -1; +static int hf_u3v_stream_trailer = -1; +static int hf_u3v_stream_payload = -1; +static int hf_u3v_ccd_cmd = -1; +static int hf_u3v_ccd_ack = -1; +static int hf_u3v_device_info_descriptor = -1; + +/* stream elements */ +static int hf_u3v_stream_reserved = -1; +static int hf_u3v_stream_leader_size = -1; + +static int hf_u3v_stream_prefix = -1; +static int hf_u3v_stream_trailer_size = -1; + +static int hf_u3v_stream_block_id = -1; +static int hf_u3v_stream_payload_type = -1; +static int hf_u3v_stream_status = -1; +static int hf_u3v_stream_valid_payload_size = -1; + +static int hf_u3v_stream_timestamp = -1; +static int hf_u3v_stream_pixel_format = -1; +static int hf_u3v_stream_size_x = -1; +static int hf_u3v_stream_size_y = -1; +static int hf_u3v_stream_offset_x = -1; +static int hf_u3v_stream_offset_y = -1; +static int hf_u3v_stream_padding_x = -1; +static int hf_u3v_stream_chunk_layout_id = -1; + +static int hf_u3v_stream_data = -1; + +/* U3V device info descriptor */ +static int hf_u3v_device_info_descriptor_bLength = -1; +static int hf_u3v_device_info_descriptor_bDescriptorType = -1; +static int hf_u3v_device_info_descriptor_bDescriptorSubtype = -1; +static int hf_u3v_device_info_descriptor_bGenCPVersion = -1; +static int hf_u3v_device_info_descriptor_bGenCPVersion_minor = -1; +static int hf_u3v_device_info_descriptor_bGenCPVersion_major = -1; +static int hf_u3v_device_info_descriptor_bU3VVersion = -1; +static int hf_u3v_device_info_descriptor_bU3VVersion_minor = -1; +static int hf_u3v_device_info_descriptor_bU3VVersion_major = -1; +static int hf_u3v_device_info_descriptor_iDeviceGUID = -1; +static int hf_u3v_device_info_descriptor_iVendorName = -1; +static int hf_u3v_device_info_descriptor_iModelName = -1; +static int hf_u3v_device_info_descriptor_iFamilyName = -1; +static int hf_u3v_device_info_descriptor_iDeviceVersion = -1; +static int hf_u3v_device_info_descriptor_iManufacturerInfo = -1; +static int hf_u3v_device_info_descriptor_iSerialNumber = -1; +static int hf_u3v_device_info_descriptor_iUserDefinedName = -1; +static int hf_u3v_device_info_descriptor_bmSpeedSupport = -1; +static int hf_u3v_device_info_descriptor_bmSpeedSupport_low_speed = -1; +static int hf_u3v_device_info_descriptor_bmSpeedSupport_full_speed = -1; +static int hf_u3v_device_info_descriptor_bmSpeedSupport_high_speed = -1; +static int hf_u3v_device_info_descriptor_bmSpeedSupport_super_speed = -1; +static int hf_u3v_device_info_descriptor_bmSpeedSupport_reserved = -1; + +/*Define the tree for u3v*/ +static int ett_u3v = -1; +static int ett_u3v_cmd = -1; +static int ett_u3v_flags = -1; +static int ett_u3v_ack = -1; +static int ett_u3v_payload_cmd = -1; +static int ett_u3v_payload_ack = -1; +static int ett_u3v_payload_cmd_subtree = -1; +static int ett_u3v_payload_ack_subtree = -1; +static int ett_u3v_bootstrap_fields = -1; +static int ett_u3v_stream_leader = -1; +static int ett_u3v_stream_trailer = -1; +static int ett_u3v_stream_payload = -1; + +static int ett_u3v_device_info_descriptor = -1; +static int ett_u3v_device_info_descriptor_speed_support = -1; +static int ett_u3v_device_info_descriptor_gencp_version = -1; +static int ett_u3v_device_info_descriptor_u3v_version = -1; + +static const value_string command_names[] = +{ + { U3V_READMEM_CMD, "READMEM_CMD" }, + { U3V_WRITEMEM_CMD, "WRITEMEM_CMD" }, + { U3V_EVENT_CMD, "EVENT_CMD" }, + { U3V_READMEM_ACK, "READMEM_ACK" }, + { U3V_WRITEMEM_ACK, "WRITEMEM_ACK" }, + { U3V_PENDING_ACK, "PENDING_ACK" }, + { U3V_EVENT_ACK, "EVENT_ACK" }, + { 0, NULL } +}; + +static const value_string event_id_names[] = +{ + { U3V_EVENT_TESTEVENT, "U3V_EVENT_TESTEVENT" }, + { 0, NULL } +}; + +static const value_string status_names[] = +{ + { U3V_STATUS_GENCP_SUCCESS, "U3V_STATUS_GENCP_SUCCESS" }, + { U3V_STATUS_GENCP_NOT_IMPLEMENTED, "U3V_STATUS_GENCP_NOT_IMPLEMENTED" }, + { U3V_STATUS_GENCP_INVALID_PARAMETER, "U3V_STATUS_GENCP_INVALID_PARAMETER" }, + { U3V_STATUS_GENCP_INVALID_ADDRESS, "U3V_STATUS_GENCP_INVALID_ADDRESS" }, + { U3V_STATUS_GENCP_WRITE_PROTECT, "U3V_STATUS_GENCP_WRITE_PROTECT" }, + { U3V_STATUS_GENCP_BAD_ALIGNMENT, "U3V_STATUS_GENCP_BAD_ALIGNMENT" }, + { U3V_STATUS_GENCP_ACCESS_DENIED, "U3V_STATUS_GENCP_ACCESS_DENIED" }, + { U3V_STATUS_GENCP_BUSY, "U3V_STATUS_GENCP_BUSY" }, + { U3V_STATUS_GENCP_WRONG_CONFIG, "U3V_STATUS_GENCP_WRONG_CONFIG" }, + { U3V_STATUS_RESEND_NOT_SUPPORTED, "U3V_STATUS_RESEND_NOT_SUPPORTED" }, + { U3V_STATUS_DSI_ENDPOINT_HALTED, "U3V_STATUS_DSI_ENDPOINT_HALTED" }, + { U3V_STATUS_SI_PAYLOAD_SIZE_NOT_ALIGNED, "U3V_STATUS_SI_PAYLOAD_SIZE_NOT_ALIGNED" }, + { U3V_STATUS_SI_REGISTERS_INCONSISTENT, "U3V_STATUS_SI_REGISTERS_INCONSISTENT" }, + { U3V_STATUS_DATA_DISCARDED, "U3V_STATUS_DATA_DISCARDED" }, + { 0, NULL } +}; + +static const value_string status_names_short[] = +{ + { U3V_STATUS_GENCP_SUCCESS, "" }, + { U3V_STATUS_GENCP_NOT_IMPLEMENTED, "U3V_STATUS_GENCP_NOT_IMPLEMENTED" }, + { U3V_STATUS_GENCP_INVALID_PARAMETER, "U3V_STATUS_GENCP_INVALID_PARAMETER" }, + { U3V_STATUS_GENCP_INVALID_ADDRESS, "U3V_STATUS_GENCP_INVALID_ADDRESS" }, + { U3V_STATUS_GENCP_WRITE_PROTECT, "U3V_STATUS_GENCP_WRITE_PROTECT" }, + { U3V_STATUS_GENCP_BAD_ALIGNMENT, "U3V_STATUS_GENCP_BAD_ALIGNMENT" }, + { U3V_STATUS_GENCP_ACCESS_DENIED, "U3V_STATUS_GENCP_ACCESS_DENIED" }, + { U3V_STATUS_GENCP_BUSY, "U3V_STATUS_GENCP_BUSY" }, + { U3V_STATUS_GENCP_WRONG_CONFIG, "U3V_STATUS_GENCP_WRONG_CONFIG" }, + { U3V_STATUS_RESEND_NOT_SUPPORTED, "U3V_STATUS_RESEND_NOT_SUPPORTED" }, + { U3V_STATUS_DSI_ENDPOINT_HALTED, "U3V_STATUS_DSI_ENDPOINT_HALTED" }, + { U3V_STATUS_SI_PAYLOAD_SIZE_NOT_ALIGNED, "U3V_STATUS_SI_PAYLOAD_SIZE_NOT_ALIGNED" }, + { U3V_STATUS_SI_REGISTERS_INCONSISTENT, "U3V_STATUS_SI_REGISTERS_INCONSISTENT" }, + { U3V_STATUS_DATA_DISCARDED, "U3V_STATUS_DATA_DISCARDED" }, + { 0, NULL } +}; + +/* + \brief Register name to address mappings + */ +static const value_string bootstrap_register_names_abrm[] = +{ + { U3V_ABRM_GENCP_VERSION, "[GenCP_Version]" }, + { U3V_ABRM_MANUFACTURER_NAME, "[Manufacturer_Name]" }, + { U3V_ABRM_MODEL_NAME, "[Model_Name]" }, + { U3V_ABRM_FAMILY_NAME, "[Family_Name]" }, + { U3V_ABRM_DEVICE_VERSION, "[Device_Version]" }, + { U3V_ABRM_MANUFACTURER_INFO, "[Manufacturer_Info]" }, + { U3V_ABRM_SERIAL_NUMBER, "[Serial_Number]" }, + { U3V_ABRM_USER_DEFINED_NAME, "[User_Defined_Name]" }, + { U3V_ABRM_DEVICE_CAPABILITY, "[Device_Capability]" }, + { U3V_ABRM_MAXIMUM_DEVICE_RESPONSE_TIME, "[Maximum_Device_Response_Time]" }, + { U3V_ABRM_MANIFEST_TABLE_ADDRESS, "[Manifest_Table_Address]" }, + { U3V_ABRM_SBRM_ADDRESS, "[SBRM_Address]" }, + { U3V_ABRM_DEVICE_CONFIGURATION, "[Device_Configuration]" }, + { U3V_ABRM_HEARTBEAT_TIMEOUT, "[Heartbeat_Timeout]" }, + { U3V_ABRM_MESSAGE_CHANNEL_CHANNEL_ID, "[Message_Channel_channel_id]" }, + { U3V_ABRM_TIMESTAMP, "[Timestamp]" }, + { U3V_ABRM_TIMESTAMP_LATCH, "[Timestamp_Latch]" }, + { U3V_ABRM_TIMESTAMP_INCREMENT, "[Timestamp_Increment]" }, + { U3V_ABRM_ACCESS_PRIVILEGE, "[Access_Privilege]" }, + { U3V_ABRM_PROTOCOL_ENDIANESS, "[Protocol_Endianess]" }, + { U3V_ABRM_IMPLEMENTATION_ENDIANESS, "[Implementation_Endianess]" }, + { 0, NULL } +}; + +static const value_string bootstrap_register_names_sbrm[] = +{ + { U3V_SBRM_U3V_VERSION, "[U3V_Version]" }, + { U3V_SBRM_U3VCP_CAPABILITY_REGISTER, "[U3VCP_Capability_Register]" }, + { U3V_SBRM_U3VCP_CONFIGURATION_REGISTER, "[U3VCP_Configuration_Register]" }, + { U3V_SBRM_MAXIMUM_COMMAND_TRANSFER_LENGTH, "[Maximum_Command_Transfer_Length]" }, + { U3V_SBRM_MAXIMUM_ACKNOWLEDGE_TRANSFER_LENGTH, "[Maximum_Acknowledge_Transfer_Length]" }, + { U3V_SBRM_NUMBER_OF_STREAM_CHANNELS, "[Number_of_Stream_Channels]" }, + { U3V_SBRM_SIRM_ADDRESS, "[SIRM_Address]" }, + { U3V_SBRM_SIRM_LENGTH, "[SIRM_Length]" }, + { U3V_SBRM_EIRM_ADDRESS, "[EIRM_Address]" }, + { U3V_SBRM_EIRM_LENGTH, "[EIRM_Length]" }, + { U3V_SBRM_IIDC2_ADDRESS, "[IIDC2_Address]" }, + { U3V_SBRM_CURRENT_SPEED, "[Current_Speed]" }, + { 0, NULL } +}; + +static const value_string bootstrap_register_names_sirm[] = +{ + { U3V_SIRM_SI_INFO, "[SI_Info]" }, + { U3V_SIRM_SI_CONTROL, "[SI_Control]" }, + { U3V_SIRM_SI_REQUIRED_PAYLOAD_SIZE, "[SI_Required_Payload_Size]" }, + { U3V_SIRM_SI_REQUIRED_LEADER_SIZE, "[SI_Required_Leader_Size]" }, + { U3V_SIRM_SI_REQUIRED_TRAILER_SIZE, "[SI_Required_Trailer_Size]" }, + { U3V_SIRM_SI_MAXIMUM_LEADER_SIZE, "[SI_Maximum_Leader_Size]" }, + { U3V_SIRM_SI_PAYLOAD_TRANSFER_SIZE, "[SI_Payload_Transfer_Size]" }, + { U3V_SIRM_SI_PAYLOAD_TRANSFER_COUNT, "[SI_Payload_Transfer_Count]" }, + { U3V_SIRM_SI_PAYLOAD_FINAL_TRANSFER1_SIZE, "[SI_Payload_Final_Transfer1_Size]" }, + { U3V_SIRM_SI_PAYLOAD_FINAL_TRANSFER2_SIZE, "[SI_Payload_Final_Transfer2_Size]" }, + { U3V_SIRM_SI_MAXIMUM_TRAILER_SIZE, "[SI_Maximum_Trailer_Size]" }, + { 0, NULL } +}; + +static const value_string bootstrap_register_names_eirm[] = +{ + { U3V_EIRM_EI_CONTROL, "[EI_Control]" }, + { U3V_EIRM_MAXIMUM_EVENT_TRANSFER_LENGTH, "[Maximum_Event_Transfer_Length]" }, + { U3V_EIRM_EVENT_TEST_CONTROL, "[Event_Test_Control]" }, + { 0, NULL } +}; + +static const value_string pixel_format_names[] = +{ + { PFNC_U3V_MONO8, "Mono8" }, + { PFNC_U3V_MONO8S, "Mono8s" }, + { PFNC_U3V_MONO10, "Mono10" }, + { PFNC_U3V_MONO10PACKED, "Mono10Packed" }, + { PFNC_U3V_MONO12, "Mono12" }, + { PFNC_U3V_MONO12PACKED, "Mono12Packed" }, + { PFNC_U3V_MONO16, "Mono16" }, + { PFNC_U3V_BAYERGR8, "BayerGR8" }, + { PFNC_U3V_BAYERRG8, "BayerRG8" }, + { PFNC_U3V_BAYERGB8, "BayerGB8" }, + { PFNC_U3V_BAYERBG8, "BayerBG8" }, + { PFNC_U3V_BAYERGR10, "BayerGR10" }, + { PFNC_U3V_BAYERRG10, "BayerRG10" }, + { PFNC_U3V_BAYERGB10, "BayerGB10" }, + { PFNC_U3V_BAYERBG10, "BayerBG10" }, + { PFNC_U3V_BAYERGR12, "BayerGR12" }, + { PFNC_U3V_BAYERRG12, "BayerRG12" }, + { PFNC_U3V_BAYERGB12, "BayerGB12" }, + { PFNC_U3V_BAYERBG12, "BayerBG12" }, + { PFNC_U3V_RGB8, "RGB8" }, + { PFNC_U3V_BGR8, "BGR8" }, + { PFNC_U3V_RGBA8, "RGBA8" }, + { PFNC_U3V_BGRA8, "BGRA8" }, + { PFNC_U3V_RGB10, "RGB10" }, + { PFNC_U3V_BGR10, "BGR10" }, + { PFNC_U3V_RGB12, "RGB12" }, + { PFNC_U3V_BGR12, "BGR12" }, + { PFNC_U3V_RGB10V1PACKED, "RGB10V1Packed" }, + { PFNC_U3V_RGB10P32, "RGB10P32" }, + { PFNC_U3V_YUV411_8_UYYVYY, "YUV411_8_UYYVYY" }, + { PFNC_U3V_YUV422_8_UYVY, "YUV422_8_UYVY" }, + { PFNC_U3V_YUV8_UYV, "YUV8_UYV" }, + { PFNC_U3V_RGB8_PLANAR, "RGB8_Planar" }, + { PFNC_U3V_RGB10_PLANAR, "RGB10_Planar" }, + { PFNC_U3V_RGB12_PLANAR, "RGB12_Planar" }, + { PFNC_U3V_RGB16_PLANAR, "RGB16_Planar" }, + { PFNC_U3V_MONO14, "Mono14" }, + { PFNC_U3V_BAYERGR10PACKED, "BayerGR10Packed" }, + { PFNC_U3V_BAYERRG10PACKED, "BayerRG10Packed" }, + { PFNC_U3V_BAYERGB10PACKED, "BayerGB10Packed" }, + { PFNC_U3V_BAYERBG10PACKED, "BayerBG10Packed" }, + { PFNC_U3V_BAYERGR12PACKED, "BayerGR12Packed" }, + { PFNC_U3V_BAYERRG12PACKED, "BayerRG12Packed" }, + { PFNC_U3V_BAYERGB12PACKED, "BayerGB12Packed" }, + { PFNC_U3V_BAYERBG12PACKED, "BayerBG12Packed" }, + { PFNC_U3V_BAYERGR16, "BayerGR16" }, + { PFNC_U3V_BAYERRG16, "BayerRG16" }, + { PFNC_U3V_BAYERGB16, "BayerGB16" }, + { PFNC_U3V_BAYERBG16, "BayerBG16" }, + { PFNC_U3V_YUV422_8, "YUV422_8" }, + { PFNC_U3V_RGB16, "RGB16" }, + { PFNC_U3V_RGB12V1PACKED, "RGB12V1Packed" }, + { PFNC_U3V_RGB565P, "RGB565p" }, + { PFNC_U3V_BGR565P, "BGR565p" }, + { PFNC_U3V_MONO1P, "Mono1p" }, + { PFNC_U3V_MONO2P, "Mono2p" }, + { PFNC_U3V_MONO4P, "Mono4p" }, + { PFNC_U3V_YCBCR8_CBYCR, "YCbCr8_CBYCR" }, + { PFNC_U3V_YCBCR422_8, "YCbCr422_8" }, + { PFNC_U3V_YCBCR411_8_CBYYCRYY, "YCbCr411_8_CBYYCRYY" }, + { PFNC_U3V_YCBCR601_8_CBYCR, "YCbCr601_8_CBYCR" }, + { PFNC_U3V_YCBCR601_422_8, "YCbCr601_422_8" }, + { PFNC_U3V_YCBCR601_411_8_CBYYCRYY, "YCbCr601_411_8_CBYYCRYY" }, + { PFNC_U3V_YCBCR709_8_CBYCR, "YCbCr709_8_CBYCR" }, + { PFNC_U3V_YCBCR709_422_8, "YCbCr709_422_8" }, + { PFNC_U3V_YCBCR709_411_8_CBYYCRYY, "YCbCr709_411_8_CBYYCRYY" }, + { PFNC_U3V_YCBCR422_8_CBYCRY, "YCbCr422_8_CBYCRY" }, + { PFNC_U3V_YCBCR601_422_8_CBYCRY, "YCbCr601_422_8_CBYCRY" }, + { PFNC_U3V_YCBCR709_422_8_CBYCRY, "YCbCr709_422_8_CBYCRY" }, + { PFNC_U3V_MONO10P, "Mono10p" }, + { PFNC_U3V_MONO12P, "Mono12p" }, + { PFNC_U3V_BGR10P, "BGR10p" }, + { PFNC_U3V_BGR12P, "BGR12p" }, + { PFNC_U3V_BGR14, "BGR14" }, + { PFNC_U3V_BGR16, "BGR16" }, + { PFNC_U3V_BGRA10, "BGRA10" }, + { PFNC_U3V_BGRA10P, "BGRA10p" }, + { PFNC_U3V_BGRA12, "BGRA12" }, + { PFNC_U3V_BGRA12P, "BGRA12p" }, + { PFNC_U3V_BGRA14, "BGRA14" }, + { PFNC_U3V_BGRA16, "BGRA16" }, + { PFNC_U3V_BAYERBG10P, "BayerBG10p" }, + { PFNC_U3V_BAYERBG12P, "BayerBG12p" }, + { PFNC_U3V_BAYERGB10P, "BayerGB10p" }, + { PFNC_U3V_BAYERGB12P, "BayerGB12p" }, + { PFNC_U3V_BAYERGR10P, "BayerGR10p" }, + { PFNC_U3V_BAYERGR12P, "BayerGR12p" }, + { PFNC_U3V_BAYERRG10P, "BayerRG10p" }, + { PFNC_U3V_BAYERRG12P, "BayerRG12p" }, + { PFNC_U3V_YCBCR411_8, "YCbCr411_8" }, + { PFNC_U3V_YCBCR8, "YCbCr8" }, + { PFNC_U3V_RGB10P, "RGB10p" }, + { PFNC_U3V_RGB12P, "RGB12p" }, + { PFNC_U3V_RGB14, "RGB14" }, + { PFNC_U3V_RGBA10, "RGBA10" }, + { PFNC_U3V_RGBA10P, "RGBA10p" }, + { PFNC_U3V_RGBA12, "RGBA12" }, + { PFNC_U3V_RGBA12P, "RGBA12p" }, + { PFNC_U3V_RGBA14, "RGBA14" }, + { PFNC_U3V_RGBA16, "RGBA16" }, + { PFNC_U3V_YCBCR422_10, "YCbCr422_10" }, + { PFNC_U3V_YCBCR422_12, "YCbCr422_12" }, + { PFNC_U3V_SCF1WBWG8, "SCF1WBWG8" }, + { PFNC_U3V_SCF1WBWG10, "SCF1WBWG10" }, + { PFNC_U3V_SCF1WBWG10P, "SCF1WBWG10p" }, + { PFNC_U3V_SCF1WBWG12, "SCF1WBWG12" }, + { PFNC_U3V_SCF1WBWG12P, "SCF1WBWG12p" }, + { PFNC_U3V_SCF1WBWG14, "SCF1WBWG14" }, + { PFNC_U3V_SCF1WBWG16, "SCF1WBWG16" }, + { PFNC_U3V_SCF1WGWB8, "SCF1WGWB8" }, + { PFNC_U3V_SCF1WGWB10, "SCF1WGWB10" }, + { PFNC_U3V_SCF1WGWB10P, "SCF1WGWB10p" }, + { PFNC_U3V_SCF1WGWB12, "SCF1WGWB12" }, + { PFNC_U3V_SCF1WGWB12P, "SCF1WGWB12p" }, + { PFNC_U3V_SCF1WGWB14, "SCF1WGWB14" }, + { PFNC_U3V_SCF1WGWB16, "SCF1WGWB16" }, + { PFNC_U3V_SCF1WGWR8, "SCF1WGWR8" }, + { PFNC_U3V_SCF1WGWR10, "SCF1WGWR10" }, + { PFNC_U3V_SCF1WGWR10P, "SCF1WGWR10p" }, + { PFNC_U3V_SCF1WGWR12, "SCF1WGWR12" }, + { PFNC_U3V_SCF1WGWR12P, "SCF1WGWR12p" }, + { PFNC_U3V_SCF1WGWR14, "SCF1WGWR14" }, + { PFNC_U3V_SCF1WGWR16, "SCF1WGWR16" }, + { PFNC_U3V_SCF1WRWG8, "SCF1WRWG8" }, + { PFNC_U3V_SCF1WRWG10, "SCF1WRWG10" }, + { PFNC_U3V_SCF1WRWG10P, "SCF1WRWG10p" }, + { PFNC_U3V_SCF1WRWG12, "SCF1WRWG12" }, + { PFNC_U3V_SCF1WRWG12P, "SCF1WRWG12p" }, + { PFNC_U3V_SCF1WRWG14, "SCF1WRWG14" }, + { PFNC_U3V_SCF1WRWG16, "SCF1WRWG16" }, + { PFNC_U3V_YCBCR10_CBYCR, "YCbCr10_CBYCR" }, + { PFNC_U3V_YCBCR10P_CBYCR, "YCbCr10P_CBYCR" }, + { PFNC_U3V_YCBCR12_CBYCR, "YCbCr12_CBYCR" }, + { PFNC_U3V_YCBCR12P_CBYCR, "YCbCr12P_CBYCR" }, + { PFNC_U3V_YCBCR422_10P, "YCbCr422_10p" }, + { PFNC_U3V_YCBCR422_12P, "YCbCr422_12p" }, + { PFNC_U3V_YCBCR601_10_CBYCR, "YCbCr601_10_CBYCR" }, + { PFNC_U3V_YCBCR601_10P_CBYCR, "YCbCr601_10P_CBYCR" }, + { PFNC_U3V_YCBCR601_12_CBYCR, "YCbCr601_12_CBYCR" }, + { PFNC_U3V_YCBCR601_12P_CBYCR, "YCbCr601_12P_CBYCR" }, + { PFNC_U3V_YCBCR601_422_10, "YCbCr601_422_10" }, + { PFNC_U3V_YCBCR601_422_10P, "YCbCr601_422_10p" }, + { PFNC_U3V_YCBCR601_422_12, "YCbCr601_422_12" }, + { PFNC_U3V_YCBCR601_422_12P, "YCbCr601_422_12p" }, + { PFNC_U3V_YCBCR709_10_CBYCR, "YCbCr709_10_CBYCR" }, + { PFNC_U3V_YCBCR709_10P_CBYCR, "YCbCr709_10P_CBYCR" }, + { PFNC_U3V_YCBCR709_12_CBYCR, "YCbCr709_12_CBYCR" }, + { PFNC_U3V_YCBCR709_12P_CBYCR, "YCbCr709_12P_CBYCR" }, + { PFNC_U3V_YCBCR709_422_10, "YCbCr709_422_10" }, + { PFNC_U3V_YCBCR709_422_10P, "YCbCr709_422_10p" }, + { PFNC_U3V_YCBCR709_422_12, "YCbCr709_422_12" }, + { PFNC_U3V_YCBCR709_422_12P, "YCbCr709_422_12p" }, + { PFNC_U3V_YCBCR422_10_CBYCRY, "YCbCr422_10_CBYCRY" }, + { PFNC_U3V_YCBCR422_10P_CBYCRY, "YCbCr422_10P_CBYCRY" }, + { PFNC_U3V_YCBCR422_12_CBYCRY, "YCbCr422_12_CBYCRY" }, + { PFNC_U3V_YCBCR422_12P_CBYCRY, "YCbCr422_12P_CBYCRY" }, + { PFNC_U3V_YCBCR601_422_10_CBYCRY, "YCbCr601_422_10_CBYCRY" }, + { PFNC_U3V_YCBCR601_422_10P_CBYCRY, "YCbCr601_422_10P_CBYCRY" }, + { PFNC_U3V_YCBCR601_422_12_CBYCRY, "YCbCr601_422_12_CBYCRY" }, + { PFNC_U3V_YCBCR601_422_12P_CBYCRY, "YCbCr601_422_12P_CBYCRY" }, + { PFNC_U3V_YCBCR709_422_10_CBYCRY, "YCbCr709_422_10_CBYCRY" }, + { PFNC_U3V_YCBCR709_422_10P_CBYCRY, "YCbCr709_422_10P_CBYCRY" }, + { PFNC_U3V_YCBCR709_422_12_CBYCRY, "YCbCr709_422_12_CBYCRY" }, + { PFNC_U3V_YCBCR709_422_12P_CBYCRY, "YCbCr709_422_12P_CBYCRY" }, + { PFNC_U3V_BICOLORRGBG8, "BICOLORRGBG8" }, + { PFNC_U3V_BICOLORBGRG8, "BICOLORBGRG8" }, + { PFNC_U3V_BICOLORRGBG10, "BICOLORRGBG10" }, + { PFNC_U3V_BICOLORRGBG10P, "BICOLORRGBG10p" }, + { PFNC_U3V_BICOLORBGRG10, "BICOLORBGRG10" }, + { PFNC_U3V_BICOLORBGRG10P, "BICOLORBGRG10p" }, + { PFNC_U3V_BICOLORRGBG12, "BICOLORRGBG12" }, + { PFNC_U3V_BICOLORRGBG12P, "BICOLORRGBG12p" }, + { PFNC_U3V_BICOLORBGRG12, "BICOLORBGRG12" }, + { PFNC_U3V_BICOLORBGRG12P, "BICOLORBGRG12p" }, + { PFNC_U3V_COORD3D_A8, "Coord3D_A8" }, + { PFNC_U3V_COORD3D_B8, "Coord3D_B8" }, + { PFNC_U3V_COORD3D_C8, "Coord3D_C8" }, + { PFNC_U3V_COORD3D_ABC8, "Coord3D_ABC8" }, + { PFNC_U3V_COORD3D_ABC8_PLANAR, "Coord3D_ABC8_Planar" }, + { PFNC_U3V_COORD3D_AC8, "Coord3D_AC8" }, + { PFNC_U3V_COORD3D_AC8_PLANAR, "Coord3D_AC8_Planar" }, + { PFNC_U3V_COORD3D_A16, "Coord3D_A16" }, + { PFNC_U3V_COORD3D_B16, "Coord3D_B16" }, + { PFNC_U3V_COORD3D_C16, "Coord3D_C16" }, + { PFNC_U3V_COORD3D_ABC16, "Coord3D_ABC16" }, + { PFNC_U3V_COORD3D_ABC16_PLANAR, "Coord3D_ABC16_Planar" }, + { PFNC_U3V_COORD3D_AC16, "Coord3D_AC16" }, + { PFNC_U3V_COORD3D_AC16_PLANAR, "Coord3D_AC16_Planar" }, + { PFNC_U3V_COORD3D_A32F, "Coord3D_A32F" }, + { PFNC_U3V_COORD3D_B32F, "Coord3D_B32F" }, + { PFNC_U3V_COORD3D_C32F, "Coord3D_C32F" }, + { PFNC_U3V_COORD3D_ABC32F, "Coord3D_ABC32F" }, + { PFNC_U3V_COORD3D_ABC32F_PLANAR, "Coord3D_ABC32F_Planar" }, + { PFNC_U3V_COORD3D_AC32F, "Coord3D_AC32F" }, + { PFNC_U3V_COORD3D_AC32F_PLANAR, "Coord3D_AC32F_Planar" }, + { PFNC_U3V_CONFIDENCE1, "CONFIDENCE1" }, + { PFNC_U3V_CONFIDENCE1P, "CONFIDENCE1p" }, + { PFNC_U3V_CONFIDENCE8, "CONFIDENCE8" }, + { PFNC_U3V_CONFIDENCE16, "CONFIDENCE16" }, + { PFNC_U3V_CONFIDENCE32F, "CONFIDENCE32F" }, + { PFNC_U3V_R8, "R8" }, + { PFNC_U3V_R10, "R10" }, + { PFNC_U3V_R12, "R12" }, + { PFNC_U3V_R16, "R16" }, + { PFNC_U3V_G8, "G8" }, + { PFNC_U3V_G10, "G10" }, + { PFNC_U3V_G12, "G12" }, + { PFNC_U3V_G16, "G16" }, + { PFNC_U3V_B8, "B8" }, + { PFNC_U3V_B10, "B10" }, + { PFNC_U3V_B12, "B12" }, + { PFNC_U3V_B16, "B16" }, + { PFNC_U3V_COORD3D_A10P, "Coord3D_A10p" }, + { PFNC_U3V_COORD3D_B10P, "Coord3D_B10p" }, + { PFNC_U3V_COORD3D_C10P, "Coord3D_C10p" }, + { PFNC_U3V_COORD3D_A12P, "Coord3D_A12p" }, + { PFNC_U3V_COORD3D_B12P, "Coord3D_B12p" }, + { PFNC_U3V_COORD3D_C12P, "Coord3D_C12p" }, + { PFNC_U3V_COORD3D_ABC10P, "Coord3D_ABC10p" }, + { PFNC_U3V_COORD3D_ABC10P_PLANAR, "Coord3D_ABC10P_Planar" }, + { PFNC_U3V_COORD3D_ABC12P, "Coord3D_ABC12p" }, + { PFNC_U3V_COORD3D_ABC12P_PLANAR, "Coord3D_ABC12P_Planar" }, + { PFNC_U3V_COORD3D_AC10P, "Coord3D_AC10p" }, + { PFNC_U3V_COORD3D_AC10P_PLANAR, "Coord3D_AC10P_Planar" }, + { PFNC_U3V_COORD3D_AC12P, "Coord3D_AC12p" }, + { PFNC_U3V_COORD3D_AC12P_PLANAR, "Coord3D_AC12P_Planar" }, + { 0, NULL } +}; + +static value_string_ext pixel_format_names_ext = VALUE_STRING_EXT_INIT(pixel_format_names); + + +static const value_string payload_type_names[] = +{ + { U3V_STREAM_PAYLOAD_IMAGE, "Image" }, + { U3V_STREAM_PAYLOAD_IMAGE_EXT_CHUNK, "Image Extended Chunk" }, + { U3V_STREAM_PAYLOAD_CHUNK, "Chunk" }, + { 0, NULL } +}; + +static const value_string u3v_descriptor_subtypes[] = +{ + { DESCRIPTOR_SUBTYPE_U3V_DEVICE_INFO, "U3V DEVICE INFO" }, + { 0, NULL } +}; + +static const int *speed_support_fields[] = { + &hf_u3v_device_info_descriptor_bmSpeedSupport_low_speed, + &hf_u3v_device_info_descriptor_bmSpeedSupport_full_speed, + &hf_u3v_device_info_descriptor_bmSpeedSupport_high_speed, + &hf_u3v_device_info_descriptor_bmSpeedSupport_super_speed, + &hf_u3v_device_info_descriptor_bmSpeedSupport_reserved, + NULL +}; + + +/* + \brief Returns a register name based on its address + */ +static const gchar* +get_register_name_from_address(guint64 addr, gboolean* is_custom_register, u3v_conv_info_t * u3v_conv_info) +{ + const gchar* address_string = NULL; + guint32 offset_address; + + if (is_custom_register != NULL) { + *is_custom_register = FALSE; + } + + /* check if this is the access to one of the base address registers */ + if ( addr < 0x10000 ) { + offset_address = (guint32)addr; + address_string = try_val_to_str(offset_address, bootstrap_register_names_abrm); + } + if ( u3v_conv_info && u3v_conv_info->sbrm_addr != 0 && (addr >= u3v_conv_info->sbrm_addr)) { + offset_address = (guint32)( addr - u3v_conv_info->sbrm_addr); + address_string = try_val_to_str(offset_address, bootstrap_register_names_sbrm); + } + if ( u3v_conv_info && u3v_conv_info->sirm_addr != 0 && (addr >= u3v_conv_info->sirm_addr)) { + offset_address = (guint32)( addr - u3v_conv_info->sirm_addr); + address_string = try_val_to_str(offset_address, bootstrap_register_names_sirm); + } + if ( u3v_conv_info && u3v_conv_info->eirm_addr != 0 && (addr >= u3v_conv_info->eirm_addr)) { + offset_address = (guint32)( addr - u3v_conv_info->eirm_addr); + address_string = try_val_to_str(offset_address, bootstrap_register_names_eirm); + } + + if (!address_string) { + address_string = wmem_strdup_printf(wmem_packet_scope(), "[Addr:0x%016" G_GINT64_MODIFIER "X]", addr); + if (is_custom_register != NULL) { + *is_custom_register = TRUE; + } + } + + return address_string; +} + +/* + \brief Returns true if a register (identified by its address) is a known bootstrap register + */ +static int +is_known_bootstrap_register(guint64 addr, u3v_conv_info_t * u3v_conv_info) +{ + const gchar* address_string = NULL; + guint32 offset_address; + /* check if this is the access to one of the base address registers */ + if ( addr < 0x10000 ) { + offset_address = (guint32)addr; + address_string = try_val_to_str(offset_address, bootstrap_register_names_abrm); + } + if ( u3v_conv_info->sbrm_addr != 0 && (addr >= u3v_conv_info->sbrm_addr)) { + offset_address = (guint32)( addr - u3v_conv_info->sbrm_addr); + address_string = try_val_to_str(offset_address, bootstrap_register_names_sbrm); + } + if ( u3v_conv_info->sirm_addr != 0 && (addr >= u3v_conv_info->sirm_addr)) { + offset_address = (guint32)( addr - u3v_conv_info->sirm_addr); + address_string = try_val_to_str(offset_address, bootstrap_register_names_sirm); + } + if ( u3v_conv_info->eirm_addr != 0 && (addr >= u3v_conv_info->eirm_addr)) { + offset_address = (guint32)( addr - u3v_conv_info->eirm_addr); + address_string = try_val_to_str(offset_address, bootstrap_register_names_eirm); + } + return address_string != NULL; +} + +/* + \brief Identify Base Address Pointer +*/ +static void +dissect_u3v_register_bases(guint64 addr, tvbuff_t *tvb, gint offset, u3v_conv_info_t * u3v_conv_info) +{ + if ( addr < 0x10000 ) { + switch (addr) { + case U3V_ABRM_SBRM_ADDRESS: + u3v_conv_info->sbrm_addr = tvb_get_letoh64(tvb, offset); + break; + case U3V_ABRM_MANIFEST_TABLE_ADDRESS: + u3v_conv_info->manifest_addr = tvb_get_letoh64(tvb, offset); + break; + } + } + if ( u3v_conv_info->sbrm_addr != 0 && (addr >= u3v_conv_info->sbrm_addr)) { + addr -= u3v_conv_info->sbrm_addr; + switch(addr) { + case U3V_SBRM_SIRM_ADDRESS: + u3v_conv_info->sirm_addr = tvb_get_letoh64(tvb, offset); + break; + case U3V_SBRM_EIRM_ADDRESS: + u3v_conv_info->eirm_addr = tvb_get_letoh64(tvb, offset); + break; + case U3V_SBRM_IIDC2_ADDRESS: + u3v_conv_info->iidc2_addr = tvb_get_letoh64(tvb, offset); + break; + } + } +} + +/* + \brief Attempt to dissect a bootstrap register +*/ +static int +dissect_u3v_register(guint64 addr, proto_tree *branch, tvbuff_t *tvb, gint offset, gint length, u3v_conv_info_t * u3v_conv_info) +{ + gint isABRM = FALSE, isSBRM = FALSE, isSIRM = FALSE,isEIRM = FALSE; + /* check if this is the access to one of the base address registers */ + if ( addr < 0x10000 ) { + isABRM = TRUE; + switch (addr) { + case U3V_ABRM_GENCP_VERSION: + proto_tree_add_item(branch, hf_u3v_bootstrap_GenCP_Version, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_ABRM_MANUFACTURER_NAME: + if ( length <= 64 ) { + proto_tree_add_item(branch, hf_u3v_bootstrap_Manufacturer_Name, tvb, offset, length, ENC_ASCII|ENC_NA); + } + break; + case U3V_ABRM_MODEL_NAME: + if ( length <= 64 ) { + proto_tree_add_item(branch, hf_u3v_bootstrap_Model_Name, tvb, offset, length, ENC_ASCII|ENC_NA); + } + break; + case U3V_ABRM_FAMILY_NAME: + if ( length <= 64 ) { + proto_tree_add_item(branch, hf_u3v_bootstrap_Family_Name, tvb, offset, length, ENC_ASCII|ENC_NA); + } + break; + case U3V_ABRM_DEVICE_VERSION: + if ( length <= 64 ) { + proto_tree_add_item(branch, hf_u3v_bootstrap_Device_Version, tvb, offset, length, ENC_ASCII|ENC_NA); + } + break; + case U3V_ABRM_MANUFACTURER_INFO: + if ( length <= 64 ) { + proto_tree_add_item(branch, hf_u3v_bootstrap_Manufacturer_Info, tvb, offset, length, ENC_ASCII|ENC_NA); + } + break; + case U3V_ABRM_SERIAL_NUMBER: + if ( length <= 64 ) { + proto_tree_add_item(branch, hf_u3v_bootstrap_Serial_Number, tvb, offset, length, ENC_ASCII|ENC_NA); + } + break; + case U3V_ABRM_USER_DEFINED_NAME: + if ( length <= 64 ) { + proto_tree_add_item(branch, hf_u3v_bootstrap_User_Defined_Name, tvb, offset, length, ENC_ASCII|ENC_NA); + } + break; + case U3V_ABRM_DEVICE_CAPABILITY: + proto_tree_add_item(branch, hf_u3v_bootstrap_Device_Capability, tvb, offset, 8, ENC_LITTLE_ENDIAN); + break; + case U3V_ABRM_MAXIMUM_DEVICE_RESPONSE_TIME: + proto_tree_add_item(branch, hf_u3v_bootstrap_Maximum_Device_Response_Time, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_ABRM_MANIFEST_TABLE_ADDRESS: + proto_tree_add_item(branch, hf_u3v_bootstrap_Manifest_Table_Address, tvb, offset, 8, ENC_LITTLE_ENDIAN); + break; + case U3V_ABRM_SBRM_ADDRESS: + proto_tree_add_item(branch, hf_u3v_bootstrap_SBRM_Address, tvb, offset, 8, ENC_LITTLE_ENDIAN); + break; + case U3V_ABRM_DEVICE_CONFIGURATION: + proto_tree_add_item(branch, hf_u3v_bootstrap_Device_Configuration, tvb, offset, 8, ENC_LITTLE_ENDIAN); + break; + case U3V_ABRM_HEARTBEAT_TIMEOUT: + proto_tree_add_item(branch, hf_u3v_bootstrap_Heartbeat_Timeout, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_ABRM_MESSAGE_CHANNEL_CHANNEL_ID: + proto_tree_add_item(branch, hf_u3v_bootstrap_Message_Channel_channel_id, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_ABRM_TIMESTAMP: + proto_tree_add_item(branch, hf_u3v_bootstrap_Timestamp, tvb, offset, 8, ENC_LITTLE_ENDIAN); + break; + case U3V_ABRM_TIMESTAMP_LATCH: + proto_tree_add_item(branch, hf_u3v_bootstrap_Timestamp_Latch, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_ABRM_TIMESTAMP_INCREMENT: + proto_tree_add_item(branch, hf_u3v_bootstrap_Timestamp_Increment, tvb, offset, 8, ENC_LITTLE_ENDIAN); + break; + case U3V_ABRM_ACCESS_PRIVILEGE: + proto_tree_add_item(branch, hf_u3v_bootstrap_Access_Privilege, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_ABRM_PROTOCOL_ENDIANESS: + proto_tree_add_item(branch, hf_u3v_bootstrap_Protocol_Endianess, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_ABRM_IMPLEMENTATION_ENDIANESS: + proto_tree_add_item(branch, hf_u3v_bootstrap_Implementation_Endianess, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + default: + isABRM = FALSE; + break; + } + } + if ( u3v_conv_info->sbrm_addr != 0 && (addr >= u3v_conv_info->sbrm_addr)) { + guint64 map_offset = addr - u3v_conv_info->sbrm_addr; + isSBRM = TRUE; + switch(map_offset) { + case U3V_SBRM_U3V_VERSION: + proto_tree_add_item(branch, hf_u3v_bootstrap_U3V_Version, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SBRM_U3VCP_CAPABILITY_REGISTER: + proto_tree_add_item(branch, hf_u3v_bootstrap_U3VCP_Capability_Register, tvb, offset, 8, ENC_LITTLE_ENDIAN); + break; + case U3V_SBRM_U3VCP_CONFIGURATION_REGISTER: + proto_tree_add_item(branch, hf_u3v_bootstrap_U3VCP_Configuration_Register, tvb, offset, 8, ENC_LITTLE_ENDIAN); + break; + case U3V_SBRM_MAXIMUM_COMMAND_TRANSFER_LENGTH: + proto_tree_add_item(branch, hf_u3v_bootstrap_Maximum_Command_Transfer_Length, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SBRM_MAXIMUM_ACKNOWLEDGE_TRANSFER_LENGTH: + proto_tree_add_item(branch, hf_u3v_bootstrap_Maximum_Acknowledge_Transfer_Length, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SBRM_NUMBER_OF_STREAM_CHANNELS: + proto_tree_add_item(branch, hf_u3v_bootstrap_Number_of_Stream_Channels, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SBRM_SIRM_ADDRESS: + proto_tree_add_item(branch, hf_u3v_bootstrap_SIRM_Address, tvb, offset, 8, ENC_LITTLE_ENDIAN); + break; + case U3V_SBRM_SIRM_LENGTH: + proto_tree_add_item(branch, hf_u3v_bootstrap_SIRM_Length, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SBRM_EIRM_ADDRESS: + proto_tree_add_item(branch, hf_u3v_bootstrap_EIRM_Address, tvb, offset, 8, ENC_LITTLE_ENDIAN); + break; + case U3V_SBRM_EIRM_LENGTH: + proto_tree_add_item(branch, hf_u3v_bootstrap_EIRM_Length, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SBRM_IIDC2_ADDRESS: + proto_tree_add_item(branch, hf_u3v_bootstrap_IIDC2_Address, tvb, offset, 8, ENC_LITTLE_ENDIAN); + break; + case U3V_SBRM_CURRENT_SPEED: + proto_tree_add_item(branch, hf_u3v_bootstrap_Current_Speed, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + default: + isSBRM = FALSE; + break; + } + } + if ( u3v_conv_info->sirm_addr != 0 && (addr >= u3v_conv_info->sirm_addr)) { + guint64 map_offset = addr - u3v_conv_info->sirm_addr; + isSIRM = TRUE; + switch(map_offset) { + case U3V_SIRM_SI_INFO: + proto_tree_add_item(branch, hf_u3v_bootstrap_SI_Info, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SIRM_SI_CONTROL: + proto_tree_add_item(branch, hf_u3v_bootstrap_SI_Control, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SIRM_SI_REQUIRED_PAYLOAD_SIZE: + proto_tree_add_item(branch, hf_u3v_bootstrap_SI_Required_Payload_Size, tvb, offset, 8, ENC_LITTLE_ENDIAN); + break; + case U3V_SIRM_SI_REQUIRED_LEADER_SIZE: + proto_tree_add_item(branch, hf_u3v_bootstrap_SI_Required_Leader_Size, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SIRM_SI_REQUIRED_TRAILER_SIZE: + proto_tree_add_item(branch, hf_u3v_bootstrap_SI_Required_Trailer_Size, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SIRM_SI_MAXIMUM_LEADER_SIZE: + proto_tree_add_item(branch, hf_u3v_bootstrap_SI_Maximum_Leader_Size, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SIRM_SI_PAYLOAD_TRANSFER_SIZE: + proto_tree_add_item(branch, hf_u3v_bootstrap_SI_Payload_Transfer_Size, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SIRM_SI_PAYLOAD_TRANSFER_COUNT: + proto_tree_add_item(branch, hf_u3v_bootstrap_SI_Payload_Transfer_Count, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SIRM_SI_PAYLOAD_FINAL_TRANSFER1_SIZE: + proto_tree_add_item(branch, hf_u3v_bootstrap_SI_Payload_Final_Transfer1_Size, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SIRM_SI_PAYLOAD_FINAL_TRANSFER2_SIZE: + proto_tree_add_item(branch, hf_u3v_bootstrap_SI_Payload_Final_Transfer2_Size, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_SIRM_SI_MAXIMUM_TRAILER_SIZE: + proto_tree_add_item(branch, hf_u3v_bootstrap_SI_Maximum_Trailer_Size, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + default: + isSIRM = FALSE; + break; + } + } + if ( u3v_conv_info->eirm_addr != 0 && (addr >= u3v_conv_info->eirm_addr)) { + guint64 map_offset = addr -u3v_conv_info->eirm_addr; + isEIRM=TRUE; + switch(map_offset) { + case U3V_EIRM_EI_CONTROL: + proto_tree_add_item(branch, hf_u3v_bootstrap_EI_Control, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_EIRM_MAXIMUM_EVENT_TRANSFER_LENGTH: + proto_tree_add_item(branch, hf_u3v_bootstrap_Maximum_Event_Transfer_Length, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + case U3V_EIRM_EVENT_TEST_CONTROL: + proto_tree_add_item(branch, hf_u3v_bootstrap_Event_Test_Control, tvb, offset, 4, ENC_LITTLE_ENDIAN); + break; + default: + isEIRM = FALSE; + break; + } + } + if(isABRM || isSBRM || isSIRM || isEIRM ) { + return 1; + } + return 0; +} + +/* + \brief DISSECT: Read memory command +*/ +static void +dissect_u3v_read_mem_cmd(proto_tree *u3v_telegram_tree, tvbuff_t *tvb, packet_info *pinfo, gint startoffset, gint length, u3v_conv_info_t *u3v_conv_info, gencp_transaction_t * gencp_trans) +{ + guint64 addr = 0; + const gchar* address_string = NULL; + gboolean is_custom_register = FALSE; + guint16 count = 0; + gint offset = startoffset; + proto_item *item = NULL; + + addr = tvb_get_letoh64(tvb, offset); + gencp_trans->address = addr; + + address_string = get_register_name_from_address(addr, &is_custom_register, u3v_conv_info); + count = tvb_get_letohs(tvb, offset + 10); /* Number of bytes to read from memory */ + + gencp_trans->count = count; + if ( 0xffffffff00000000 & addr ) { + col_append_fstr(pinfo->cinfo, COL_INFO, " (0x%016" G_GINT64_MODIFIER "X (%d) bytes) %s", addr, count, address_string); + } else { + col_append_fstr(pinfo->cinfo, COL_INFO, " (0x%08X (%d) bytes)", (guint32)addr, count); + } + + + item = proto_tree_add_item(u3v_telegram_tree, hf_u3v_scd_readmem_cmd, tvb, offset, length, ENC_NA); + u3v_telegram_tree = proto_item_add_subtree(item, ett_u3v_payload_cmd); + + /* address */ + if (is_known_bootstrap_register(addr, u3v_conv_info)) { + item = proto_tree_add_uint64(u3v_telegram_tree, hf_u3v_address, tvb, offset, 8, addr); + proto_item_append_text(item, " %s", address_string); + } else { + item = proto_tree_add_item(u3v_telegram_tree, hf_u3v_custom_memory_addr, tvb, offset, 8, ENC_LITTLE_ENDIAN); + } + offset += 8; + + /* reserved field */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + + /* count */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_count, tvb, offset, 2, ENC_LITTLE_ENDIAN); +} + +/* + \brief DISSECT: Write memory command +*/ +static void +dissect_u3v_write_mem_cmd(proto_tree *u3v_telegram_tree, tvbuff_t *tvb, packet_info *pinfo, gint startoffset, gint length, u3v_conv_info_t *u3v_conv_info, gencp_transaction_t *gencp_trans) +{ + const gchar* address_string = NULL; + gboolean is_custom_register = FALSE; + guint64 addr = 0; + guint byte_count = 0; + proto_item *item = NULL; + guint offset = startoffset + 8; + + addr = tvb_get_letoh64(tvb, startoffset); + byte_count = length - 8; + address_string = get_register_name_from_address(addr, &is_custom_register, u3v_conv_info); + + gencp_trans->address = addr; + gencp_trans->count = byte_count; + + /* fill in Info column in Wireshark GUI */ + col_append_fstr(pinfo->cinfo, COL_INFO, "%s: %d bytes", address_string, byte_count); + + + /* Subtree initialization for Payload Data: WRITEMEM_CMD */ + item = proto_tree_add_item(u3v_telegram_tree, hf_u3v_scd_writemem_cmd, tvb, startoffset, length, ENC_NA); + u3v_telegram_tree = proto_item_add_subtree(item, ett_u3v_payload_cmd); + + if (is_known_bootstrap_register(addr, u3v_conv_info)) { + item = proto_tree_add_uint64(u3v_telegram_tree, hf_u3v_address, tvb, startoffset, 8, addr); + proto_item_append_text(item, " %s", address_string); + dissect_u3v_register(addr, u3v_telegram_tree, tvb, offset, byte_count, u3v_conv_info); + } else { + proto_tree_add_item(u3v_telegram_tree, hf_u3v_custom_memory_addr, tvb, startoffset, 8, ENC_LITTLE_ENDIAN); + proto_tree_add_item(u3v_telegram_tree, hf_u3v_custom_memory_data, tvb, startoffset + 8, byte_count, ENC_NA); + } + +} + +/* + * \brief DISSECT: Event command + */ +static void +dissect_u3v_event_cmd(proto_tree *u3v_telegram_tree, tvbuff_t *tvb, packet_info *pinfo, gint startoffset, gint length) +{ + gint32 eventid; + gint offset = startoffset; + proto_item *item = NULL; + + /* Get event ID */ + eventid = tvb_get_letohs(tvb, offset + 2); + + /* fill in Info column in Wireshark GUI */ + col_append_fstr(pinfo->cinfo, COL_INFO, "[ID: 0x%04X]", eventid); + + + item = proto_tree_add_item(u3v_telegram_tree, hf_u3v_scd_event_cmd, tvb, offset, length, ENC_NA); + u3v_telegram_tree = proto_item_add_subtree(item, ett_u3v_payload_cmd); + + offset += 2; + + /* Use range to determine type of event */ + if ((eventid >= 0x0000) && (eventid <= 0x8000)) { + /* Standard ID */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_eventcmd_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); + } else if ((eventid >= 0x8001) && (eventid <= 0x8FFF)) { + /* Error */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_eventcmd_error_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); + } else if ((eventid >= 0x9000) && (eventid <= 0xFFFF)) { + /* Device specific */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_eventcmd_device_specific_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); + } + offset += 2; + + /* Timestamp (64 bit) associated with event */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_eventcmd_timestamp, tvb, offset, 8, ENC_LITTLE_ENDIAN); + offset += 8; + + /* Data */ + if (length > offset ) { + proto_tree_add_item(u3v_telegram_tree, hf_u3v_eventcmd_data, tvb, offset, length - 12, ENC_NA); + } +} + +/* + \brief DISSECT: Read memory acknowledge +*/ +static void +dissect_u3v_read_mem_ack(proto_tree *u3v_telegram_tree, tvbuff_t *tvb, packet_info *pinfo, gint startoffset, gint length, u3v_conv_info_t *u3v_conv_info, gencp_transaction_t * gencp_trans) +{ + guint64 addr = 0; + const gchar *address_string = NULL; + gboolean is_custom_register = FALSE; + gboolean have_address = (0 != gencp_trans->cmd_frame); + proto_item *item = NULL; + guint offset = startoffset; + guint byte_count = (length); + + addr = gencp_trans->address; + dissect_u3v_register_bases(addr, tvb, startoffset, u3v_conv_info); + if (have_address) { + address_string = get_register_name_from_address(addr, &is_custom_register, u3v_conv_info); + /* Fill in Wireshark GUI Info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, "%s", address_string); + } + + + /* Subtree initialization for Payload Data: READMEM_ACK */ + item = proto_tree_add_item(u3v_telegram_tree, hf_u3v_scd_ack_readmem_ack, tvb, startoffset, length, ENC_NA); + u3v_telegram_tree = proto_item_add_subtree(item, ett_u3v_payload_cmd); + + /* Bootstrap register known address */ + if (have_address) { + item = proto_tree_add_uint64(u3v_telegram_tree, hf_u3v_address, tvb, 0,0 , addr); + PROTO_ITEM_SET_GENERATED(item); + + if (is_known_bootstrap_register(addr, u3v_conv_info)) { + dissect_u3v_register(addr, u3v_telegram_tree, tvb, offset, byte_count, u3v_conv_info); + } else { + item = proto_tree_add_item(u3v_telegram_tree, hf_u3v_custom_memory_data, tvb, startoffset, length, ENC_NA); + } + } +} + +/* + \brief DISSECT: Write memory acknowledge +*/ +static void +dissect_u3v_write_mem_ack(proto_tree *u3v_telegram_tree, tvbuff_t *tvb, packet_info *pinfo, gint startoffset, gint length, u3v_conv_info_t *u3v_conv_info , gencp_transaction_t * gencp_trans) +{ + guint64 addr = 0; + gint offset = startoffset; + const gchar *address_string = NULL; + gboolean is_custom_register = FALSE; + gboolean have_address = (0 != gencp_trans->cmd_frame); + proto_item *item = NULL; + + addr = gencp_trans->address; + if (have_address) { + address_string = get_register_name_from_address(addr, &is_custom_register, u3v_conv_info); + + /* Fill in Wireshark GUI Info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, "%s", address_string); + } + + item = proto_tree_add_item(u3v_telegram_tree, hf_u3v_scd_writemem_ack, tvb, startoffset, length, ENC_NA); + u3v_telegram_tree = proto_item_add_subtree(item, ett_u3v_payload_cmd); + + if (have_address) { + item = proto_tree_add_uint64(u3v_telegram_tree, hf_u3v_address, tvb, 0,0 , addr); + PROTO_ITEM_SET_GENERATED(item); + } + /* Number of bytes successfully written to the device register map */ + if ( length == 4 ) { + + /* reserved field */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + + proto_tree_add_item(u3v_telegram_tree, hf_u3v_count, tvb, offset, 2, ENC_LITTLE_ENDIAN); + } +} + +/* + \brief DISSECT: Pending acknowledge +*/ +static void +dissect_u3v_pending_ack(proto_tree *u3v_telegram_tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint startoffset, gint length, u3v_conv_info_t *u3v_conv_info _U_, gencp_transaction_t *gencp_trans _U_) +{ + proto_item *item = NULL; + guint offset = startoffset; + + /* Fill in Wireshark GUI Info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, " %d ms", tvb_get_letohs(tvb, startoffset+2)); + + item = proto_tree_add_item(u3v_telegram_tree, hf_u3v_ccd_pending_ack, tvb, startoffset, length, ENC_NA); + u3v_telegram_tree = proto_item_add_subtree(item, ett_u3v_payload_cmd); + + /* reserved field */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + + proto_tree_add_item(u3v_telegram_tree, hf_u3v_time_to_completion, tvb, offset, 2, ENC_LITTLE_ENDIAN); +} + +/* + \brief DISSECT: Stream Leader +*/ +static void +dissect_u3v_stream_leader(proto_tree *u3v_telegram_tree, tvbuff_t *tvb, packet_info *pinfo, usb_conv_info_t *usb_conv_info _U_) +{ + guint32 offset = 0; + guint32 payload_type = 0; + guint64 block_id = 0; + proto_item *item = NULL; + + /* Subtree initialization for Stream Leader */ + item = proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_leader, tvb, 0, -1, ENC_NA); + u3v_telegram_tree = proto_item_add_subtree(item, ett_u3v_stream_leader); + + /* Add the prefix code: */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_prefix, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + + /* reserved field */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + + /* leader size */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_leader_size, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + + /* block id */ + block_id = tvb_get_letoh64(tvb, offset); + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_block_id, tvb, offset, 8, ENC_LITTLE_ENDIAN); + offset += 8; + + /* reserved field */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + + /* payload type */ + payload_type = tvb_get_letohs(tvb, offset); + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_payload_type, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + + /* Add payload type to information string */ + col_append_fstr(pinfo->cinfo, COL_INFO, "Stream Leader [ Block ID: %" G_GINT64_MODIFIER "u , Type %s]", + block_id, + val_to_str(payload_type, payload_type_names, "Unknown Payload Type")); + + if (payload_type == U3V_STREAM_PAYLOAD_IMAGE || + payload_type == U3V_STREAM_PAYLOAD_IMAGE_EXT_CHUNK || + payload_type == U3V_STREAM_PAYLOAD_CHUNK) { + /* timestamp */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_timestamp, tvb, offset, 8, ENC_LITTLE_ENDIAN); + offset += 8; + } + + if (payload_type == U3V_STREAM_PAYLOAD_IMAGE || + payload_type == U3V_STREAM_PAYLOAD_IMAGE_EXT_CHUNK ) { + /* pixel format */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_pixel_format, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + + /* size_x */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_size_x, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + + /* size_y */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_size_y, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + + /* offset_x */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_offset_x, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + + /* offset_x */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_offset_y, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + + /* padding_x */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_padding_x, tvb, offset, 2, ENC_LITTLE_ENDIAN); + /* offset += 2; */ + + /* reserved field */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_reserved, tvb, offset, 2, ENC_NA); + /* offset += 2; */ + } +} + +/* + \brief DISSECT: Stream Trailer +*/ +static void +dissect_u3v_stream_trailer(proto_tree *u3v_telegram_tree, tvbuff_t *tvb, packet_info *pinfo, usb_conv_info_t *usb_conv_info _U_) +{ + gint offset = 0; + guint64 block_id; + proto_item *item = NULL; + + /* Subtree initialization for Stream Leader */ + item = proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_trailer, tvb, 0, -1, ENC_NA); + u3v_telegram_tree = proto_item_add_subtree(item, ett_u3v_stream_trailer); + + /* Add the prefix code: */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_prefix, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + + /* reserved field */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + + /* trailer size */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_trailer_size, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + + /* block id */ + block_id = tvb_get_letoh64(tvb, offset); + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_block_id, tvb, offset, 8, ENC_LITTLE_ENDIAN); + offset += 8; + + /* status*/ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_status, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + + /* reserved field */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + + /* block id */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_valid_payload_size, tvb, offset, 8, ENC_LITTLE_ENDIAN); + offset += 8; + + /* Add payload type to information string */ + col_append_fstr(pinfo->cinfo, COL_INFO, "Stream Trailer [ Block ID: %" G_GINT64_MODIFIER "u]", block_id); + + if (tvb_captured_length_remaining(tvb,offset) >=4 ) { + /* size_y */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_size_y, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + } + + if (tvb_captured_length_remaining(tvb,offset) >=4 ) { + /* chunk layout id */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_chunk_layout_id, tvb, offset, 4, ENC_LITTLE_ENDIAN); + /* offset += 4; */ + } +} + +/* + \brief DISSECT: Stream Payload +*/ +static void +dissect_u3v_stream_payload(proto_tree *u3v_telegram_tree, tvbuff_t *tvb, packet_info *pinfo, usb_conv_info_t *usb_conv_info _U_) +{ + proto_item *item = NULL; + + /* Subtree initialization for Stream Leader */ + item = proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_payload, tvb, 0, -1, ENC_NA); + u3v_telegram_tree = proto_item_add_subtree(item, ett_u3v_stream_payload); + + /* Data */ + proto_tree_add_item(u3v_telegram_tree, hf_u3v_stream_data, tvb, 0, -1, ENC_NA); + + /* Add payload type to information string */ + col_append_fstr(pinfo->cinfo, COL_INFO, "Stream Payload"); +} + +/* + \brief Point of entry of all U3V packet dissection +*/ +static int +dissect_u3v(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + gint offset = 0; + proto_tree *u3v_tree = NULL, *ccd_tree_flag, *u3v_telegram_tree = NULL, *ccd_tree = NULL; + gint data_length = 0; + gint req_id = 0; + gint command_id = -1; + gint status = 0; + guint prefix = 0; + proto_item *ti = NULL; + proto_item *item = NULL; + const char *command_string; + usb_conv_info_t *usb_conv_info; + gint stream_detected = FALSE; + gint control_detected = FALSE; + u3v_conv_info_t *u3v_conv_info = NULL; + gencp_transaction_t *gencp_trans = NULL; + + usb_conv_info = (usb_conv_info_t *)data; + + /* decide if this packet belongs to U3V protocol */ + u3v_conv_info = (u3v_conv_info_t *)usb_conv_info->class_data; + + if (!u3v_conv_info) { + u3v_conv_info = wmem_new0(wmem_file_scope(), u3v_conv_info_t); + usb_conv_info->class_data = u3v_conv_info; + } + + /* it should be possible to also match on + * usb_conv_info->interfaceSubclass and usb_conv_info->interfaceProtocol + * but it seems that this information is not correctly setup during + * descriptor parsing + */ + prefix = tvb_get_letohl(tvb, 0); + if ((tvb_reported_length(tvb) >= 4) && ( ( U3V_CONTROL_PREFIX == prefix ) || ( U3V_EVENT_PREFIX == prefix ) ) ) { + control_detected = TRUE; + } + + if (((tvb_reported_length(tvb) >= 4) && (( U3V_STREAM_LEADER_PREFIX == prefix ) || ( U3V_STREAM_TRAILER_PREFIX == prefix ))) + || (usb_conv_info->endpoint == u3v_conv_info->ep_stream)) { + stream_detected = TRUE; + } + + if ( control_detected ) { + /* Set the protocol column */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "U3V"); + + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo, COL_INFO); + + /* Adds "USB3Vision" heading to protocol tree */ + /* We will add fields to this using the u3v_tree pointer */ + ti = proto_tree_add_item(tree, proto_u3v, tvb, offset, -1, ENC_NA); + u3v_tree = proto_item_add_subtree(ti, ett_u3v); + + prefix = tvb_get_letohl(tvb, offset); + command_id = tvb_get_letohs(tvb, offset+6); + + /* decode CCD ( DCI/DCE command data layout) */ + if ((prefix == U3V_CONTROL_PREFIX || prefix == U3V_EVENT_PREFIX) && ((command_id % 2) == 0)) { + command_string = val_to_str(command_id,command_names,"Unknown Command (0x%x)"); + item = proto_tree_add_item(u3v_tree, hf_u3v_ccd_cmd, tvb, offset, 8, ENC_NA); + proto_item_append_text(item, ": %s", command_string); + ccd_tree = proto_item_add_subtree(item, ett_u3v_cmd); + + /* Add the prefix code: */ + proto_tree_add_item(ccd_tree, hf_u3v_gencp_prefix, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + + /* Add the flags */ + item = proto_tree_add_item(ccd_tree, hf_u3v_flag, tvb, offset, 2, ENC_LITTLE_ENDIAN); + ccd_tree_flag = proto_item_add_subtree(item, ett_u3v_flags); + proto_tree_add_item(ccd_tree_flag, hf_u3v_acknowledge_required_flag, tvb, offset, 2, ENC_LITTLE_ENDIAN); + + offset += 2; + col_append_fstr(pinfo->cinfo, COL_INFO, "> %s ", command_string); + } else if (prefix == U3V_CONTROL_PREFIX && ((command_id % 2) == 1)) { + command_string = val_to_str(command_id,command_names,"Unknown Acknowledge (0x%x)"); + item = proto_tree_add_item(u3v_tree, hf_u3v_ccd_ack, tvb, offset, 8, ENC_NA); + proto_item_append_text(item, ": %s", command_string); + ccd_tree = proto_item_add_subtree(item, ett_u3v_ack); + + /* Add the prefix code: */ + proto_tree_add_item(ccd_tree, hf_u3v_gencp_prefix, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + + /* Add the status: */ + proto_tree_add_item(ccd_tree, hf_u3v_status, tvb, offset, 2,ENC_LITTLE_ENDIAN); + status = tvb_get_letohs(tvb, offset); + offset += 2; + col_append_fstr(pinfo->cinfo, COL_INFO, "< %s %s", + command_string, + val_to_str(status, status_names_short, "Unknown status (0x%04X)")); + } else { + return 0; + } + + /* Add the command id*/ + proto_tree_add_item(ccd_tree, hf_u3v_command_id, tvb, offset, 2,ENC_LITTLE_ENDIAN); + offset += 2; + + /* Parse the second part of both the command and the acknowledge header: + 0 15 16 31 + -------- -------- -------- -------- + | status | acknowledge | + -------- -------- -------- -------- + | length | req_id | + -------- -------- -------- -------- + + Add the data length + Number of valid data bytes in this message, not including this header. This + represents the number of bytes of payload appended after this header */ + + proto_tree_add_item(ccd_tree, hf_u3v_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); + data_length = tvb_get_letohs(tvb, offset); + offset += 2; + + /* Add the request ID */ + proto_tree_add_item(ccd_tree, hf_u3v_request_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); + req_id = tvb_get_letohs(tvb, offset); + offset += 2; + + /* Add telegram subtree */ + u3v_telegram_tree = proto_item_add_subtree(u3v_tree, ett_u3v); + + if (!PINFO_FD_VISITED(pinfo)) { + if ((command_id % 2) == 0) { + /* This is a command */ + gencp_trans = wmem_new(wmem_file_scope(), gencp_transaction_t); + gencp_trans->cmd_frame = pinfo->fd->num; + gencp_trans->ack_frame = 0; + gencp_trans->cmd_time = pinfo->fd->abs_ts; + /* add reference to current packet */ + p_add_proto_data(wmem_file_scope(), pinfo, proto_u3v, req_id, gencp_trans); + /* add reference to current */ + u3v_conv_info->trans_info = gencp_trans; + } else { + gencp_trans = u3v_conv_info->trans_info; + if (gencp_trans) { + gencp_trans->ack_frame = pinfo->fd->num; + /* add reference to current packet */ + p_add_proto_data(wmem_file_scope(), pinfo, proto_u3v, req_id, gencp_trans); + } + } + } else { + gencp_trans = (gencp_transaction_t*)p_get_proto_data(wmem_file_scope(),pinfo, proto_u3v, req_id); + } + + if (!gencp_trans) { + /* create a "fake" gencp_trans structure */ + gencp_trans = wmem_new(wmem_packet_scope(), gencp_transaction_t); + gencp_trans->cmd_frame = 0; + gencp_trans->ack_frame = 0; + gencp_trans->cmd_time = pinfo->fd->abs_ts; + } + + /* dissect depending on command? */ + switch (command_id) { + case U3V_READMEM_CMD: + dissect_u3v_read_mem_cmd(u3v_telegram_tree, tvb, pinfo, offset, data_length,u3v_conv_info,gencp_trans); + break; + case U3V_WRITEMEM_CMD: + dissect_u3v_write_mem_cmd(u3v_telegram_tree, tvb, pinfo, offset, data_length,u3v_conv_info,gencp_trans); + break; + case U3V_EVENT_CMD: + dissect_u3v_event_cmd(u3v_telegram_tree, tvb, pinfo, offset, data_length); + break; + case U3V_READMEM_ACK: + if ( U3V_STATUS_GENCP_SUCCESS == status ) { + dissect_u3v_read_mem_ack(u3v_telegram_tree, tvb, pinfo, offset, data_length,u3v_conv_info,gencp_trans); + } + break; + case U3V_WRITEMEM_ACK: + dissect_u3v_write_mem_ack(u3v_telegram_tree, tvb, pinfo, offset, data_length, u3v_conv_info,gencp_trans); + break; + case U3V_PENDING_ACK: + dissect_u3v_pending_ack(u3v_telegram_tree, tvb, pinfo, offset, data_length, u3v_conv_info,gencp_trans); + break; + default: + proto_tree_add_item(u3v_telegram_tree, hf_u3v_payloaddata, tvb, offset, data_length, ENC_NA); + break; + } + return data_length + 12; + } else if ( stream_detected ) { + /* this is streaming data */ + + /* init this stream configuration */ + u3v_conv_info = (u3v_conv_info_t *)usb_conv_info->class_data; + u3v_conv_info->ep_stream = usb_conv_info->endpoint; + + /* Set the protocol column */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "U3V"); + + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo, COL_INFO); + + /* Adds "USB3Vision" heading to protocol tree */ + /* We will add fields to this using the u3v_tree pointer */ + ti = proto_tree_add_item(tree, proto_u3v, tvb, offset, -1, ENC_NA); + u3v_tree = proto_item_add_subtree(ti, ett_u3v); + + if(tvb_captured_length(tvb) >=4) { + prefix = tvb_get_letohl(tvb, offset); + switch (prefix) { + case U3V_STREAM_LEADER_PREFIX: + dissect_u3v_stream_leader(u3v_tree, tvb, pinfo, usb_conv_info); + break; + case U3V_STREAM_TRAILER_PREFIX: + dissect_u3v_stream_trailer(u3v_tree, tvb, pinfo, usb_conv_info); + break; + default: + dissect_u3v_stream_payload(u3v_tree, tvb, pinfo, usb_conv_info); + break; + } + } + return tvb_captured_length(tvb); + } + return 0; +} + + +static gboolean +dissect_u3v_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + guint32 prefix; + usb_conv_info_t *usb_conv_info =NULL; + u3v_conv_info_t *u3v_conv_info =NULL; + + /* check if stream endpoint has been already set up for this conversation */ + usb_conv_info = (usb_conv_info_t *)data; + u3v_conv_info = (u3v_conv_info_t *)usb_conv_info->class_data; + + + /* all control and meta data packets of U3V contain at least the prefix */ + if (tvb_reported_length(tvb) < 4) { + return FALSE; + } + + /* either right prefix or the endpoint of the current transfer has been recognized as stream endpoint already */ + prefix = tvb_get_letohl(tvb, 0); + if ((U3V_STREAM_LEADER_PREFIX == prefix) || (U3V_STREAM_TRAILER_PREFIX == prefix) || + (U3V_CONTROL_PREFIX == prefix) || (U3V_EVENT_PREFIX == prefix) || + ( u3v_conv_info && (usb_conv_info->endpoint == u3v_conv_info->ep_stream))) { + dissect_u3v(tvb, pinfo, tree, data); + return TRUE; + } + return FALSE; +} + +static gint +dissect_u3v_descriptors(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_) +{ + guint8 type; + gint offset = 0; + proto_item * ti; + proto_tree * sub_tree; + guint32 version; + + + /* The descriptor must at least have a length and type field. */ + if (tvb_reported_length(tvb) < 2) { + return 0; + } + + /* skip len */ + type = tvb_get_guint8(tvb, 1); + + /* Check for U3V device info descriptor. */ + if (type != DESCRIPTOR_TYPE_U3V_INTERFACE) { + return 0; + } + + ti = proto_tree_add_item(tree, hf_u3v_device_info_descriptor, tvb, offset, -1, ENC_NA); + tree = proto_item_add_subtree(ti, ett_u3v_device_info_descriptor); + + /* bLength */ + proto_tree_add_item(tree, hf_u3v_device_info_descriptor_bLength, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + + /* bDescriptorType */ + ti = proto_tree_add_item(tree, hf_u3v_device_info_descriptor_bDescriptorType, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_item_append_text(ti, " (U3V INTERFACE)"); + offset++; + + /* bDescriptorSubtype */ + proto_tree_add_item(tree, hf_u3v_device_info_descriptor_bDescriptorSubtype, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + + /* bGenCPVersion */ + if (!tvb_bytes_exist(tvb, offset, 4)) { + /* Version not completely in buffer -> break dissection here. */ + return offset; + } + version = tvb_get_letohl(tvb, offset); + ti = proto_tree_add_item(tree, hf_u3v_device_info_descriptor_bGenCPVersion, tvb, offset, 4, ENC_NA); + proto_item_append_text(ti, ": %u.%u", version >> 16, version & 0xFFFF); + sub_tree = proto_item_add_subtree(ti, ett_u3v_device_info_descriptor_gencp_version); + proto_tree_add_item(sub_tree, hf_u3v_device_info_descriptor_bGenCPVersion_minor, tvb, offset, 4, ENC_LITTLE_ENDIAN); + proto_tree_add_item(sub_tree, hf_u3v_device_info_descriptor_bGenCPVersion_major, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + + /* bU3VVersion */ + if (!tvb_bytes_exist(tvb, offset, 4)) { + /* Version not completely in buffer -> break dissection here. */ + return offset; + } + version = tvb_get_letohl(tvb, offset); + ti = proto_tree_add_item(tree, hf_u3v_device_info_descriptor_bU3VVersion, tvb, offset, 4, ENC_NA); + proto_item_append_text(ti, ": %u.%u", version >> 16, version & 0xFFFF); + sub_tree = proto_item_add_subtree(ti, ett_u3v_device_info_descriptor_u3v_version); + proto_tree_add_item(sub_tree, hf_u3v_device_info_descriptor_bU3VVersion_minor, tvb, offset, 4, ENC_LITTLE_ENDIAN); + proto_tree_add_item(sub_tree, hf_u3v_device_info_descriptor_bU3VVersion_major, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + + /* iDeviceGUID */ + proto_tree_add_item(tree, hf_u3v_device_info_descriptor_iDeviceGUID, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + + /* iVendorName */ + proto_tree_add_item(tree, hf_u3v_device_info_descriptor_iVendorName, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + + /* iModelName */ + proto_tree_add_item(tree, hf_u3v_device_info_descriptor_iModelName, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + + /* iFamilyName */ + proto_tree_add_item(tree, hf_u3v_device_info_descriptor_iFamilyName, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + + /* iDeviceVersion */ + proto_tree_add_item(tree, hf_u3v_device_info_descriptor_iDeviceVersion, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + + /* iManufacturerInfo */ + proto_tree_add_item(tree, hf_u3v_device_info_descriptor_iManufacturerInfo, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + + /* iSerialNumber */ + proto_tree_add_item(tree, hf_u3v_device_info_descriptor_iSerialNumber, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + + /* iUserDefinedName */ + proto_tree_add_item(tree, hf_u3v_device_info_descriptor_iUserDefinedName, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + + /* bmSpeedSupport */ + proto_tree_add_bitmask(tree, tvb, offset, hf_u3v_device_info_descriptor_bmSpeedSupport, + ett_u3v_device_info_descriptor_speed_support, speed_support_fields, ENC_LITTLE_ENDIAN); + + offset++; + + return offset; +} + +/* + \brief Structures for register dissection + */ +static hf_register_info hf[] = +{ + /* Common U3V data */ + { &hf_u3v_gencp_prefix, + { "Prefix", "u3v.gencp.prefix", + FT_UINT8, BASE_HEX, NULL, 0x0, + "U3V GenCP Prefix", HFILL + } }, + + { &hf_u3v_flag, + { "Flags", "u3v.gencp.flags", + FT_UINT16, BASE_HEX, NULL, 0x0, + "U3V Flags", HFILL + } }, + + { &hf_u3v_acknowledge_required_flag, + { "Acknowledge Required", "u3v.gencp.flag.acq_required", + FT_BOOLEAN, 16, NULL, 0x4000, + "U3V Acknowledge Required", HFILL + } }, + + { &hf_u3v_command_id, + { "Command", "u3v.gencp.command_id", + FT_UINT16, BASE_HEX, VALS( command_names ), 0x0, + "U3V Command", HFILL + } }, + + { &hf_u3v_length, + { "Payload Length", "u3v.gencp.payloadlength", + FT_UINT16, BASE_HEX_DEC, NULL, 0x0, + "U3V Payload Length", HFILL + } }, + + { &hf_u3v_request_id, + { "Request ID", "u3v.gencp.req_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + "U3V Request ID", HFILL + } }, + + { &hf_u3v_payloaddata, + { "Payload Data", "u3v.gencp.payloaddata", + FT_BYTES, BASE_NONE, NULL, 0x0, + "U3V Payload", HFILL + } }, + + { &hf_u3v_status, + { "Status", "u3v.gencp.status", + FT_UINT16, BASE_HEX, VALS( status_names ), 0x0, + "U3V Status", HFILL + } }, + + /* Read memory */ + { &hf_u3v_address, + { "Address", "u3v.gencp.address", + FT_UINT64, BASE_HEX, NULL, 0x0, + "U3V Address", HFILL } }, + + { &hf_u3v_count, + { "Count", "u3v.gencp.count", + FT_UINT16, BASE_HEX_DEC, NULL, 0x0, + "U3V Count", HFILL + } }, + + /* Event */ + + { &hf_u3v_eventcmd_id, + { "ID", "u3v.cmd.event.id", + FT_UINT16, BASE_HEX_DEC, VALS( event_id_names ), 0x0, + "U3V Event ID", HFILL + } }, + + { &hf_u3v_eventcmd_error_id, + { "Error ID", "u3v.cmd.event.errorid", + FT_UINT16, BASE_HEX_DEC, NULL, 0x0, + "U3V Event Error ID", HFILL + } }, + + { &hf_u3v_eventcmd_device_specific_id, + { "Device Specific ID", "u3v.cmd.event.devicespecificid", + FT_UINT16, BASE_HEX_DEC, NULL, 0x0, + "U3V Event Device Specific ID", HFILL + } }, + + { &hf_u3v_eventcmd_timestamp, + { "Timestamp", "u3v.cmd.event.timestamp", + FT_UINT64, BASE_HEX_DEC, NULL, 0x0, + "U3V Event Timestamp", HFILL + } }, + + { &hf_u3v_eventcmd_data, + { "Data", "u3v.cmd.event.data", + FT_BYTES, BASE_NONE, NULL, 0x0, + "U3V Event Data", HFILL + } }, + + /* Pending acknowledge */ + { &hf_u3v_time_to_completion, + { "Time to completion", "u3v.gencp.timetocompletion", + FT_UINT16, BASE_DEC, NULL, 0x0, + "U3V Time to completion [ms]", HFILL + } }, + + { &hf_u3v_reserved, + { "Reserved", "u3v.reserved", + FT_BYTES, BASE_NONE, NULL, 0, + NULL, HFILL + } }, + + /* Custom */ + { &hf_u3v_custom_memory_addr, + { "Custom Memory Address", "u3v.gencp.custom_addr", + FT_UINT64, BASE_HEX, NULL, 0x0, + "U3V Custom Memory Address", HFILL + } }, + + { &hf_u3v_custom_memory_data, + { "Custom Memory Data", "u3v.gencp.custom_data", + FT_BYTES, BASE_NONE, NULL, 0x0, + "U3V Custom Memory Data", HFILL + } }, + + /* Bootstrap Defines */ + { &hf_u3v_bootstrap_GenCP_Version, + { "GenCP Version", "u3v.bootstrap.GenCP_Version", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Complying GenCP Version", HFILL + } }, + + { &hf_u3v_bootstrap_Manufacturer_Name, + { "Manufacturer Name", "u3v.bootstrap.Manufacturer_Name", + FT_STRING, BASE_NONE, NULL, 0x0, + "String containing the self-describing name of the manufacturer", HFILL + } }, + + { &hf_u3v_bootstrap_Model_Name, + { "Model Name", "u3v.bootstrap.Model_Name", + FT_STRING, BASE_NONE, NULL, 0x0, + "String containing the self-describing name of the device model", HFILL + } }, + + { &hf_u3v_bootstrap_Family_Name, + { "Family Name", "u3v.bootstrap.Family_Name", + FT_STRING, BASE_NONE, NULL, 0x0, + "String containing the name of the family of this device", HFILL + } }, + + { &hf_u3v_bootstrap_Device_Version, + { "Device Version", "u3v.bootstrap.Device_Version", + FT_STRING, BASE_NONE, NULL, 0x0, + "String containing the version of this device", HFILL + } }, + + { &hf_u3v_bootstrap_Manufacturer_Info, + { "Manufacturer Information", "u3v.bootstrap.Manufacturer_Info", + FT_STRING, BASE_NONE, NULL, 0x0, + "String containing additional manufacturer information", HFILL + } }, + + { &hf_u3v_bootstrap_Serial_Number, + { "Serial Number", "u3v.bootstrap.Serial_Number", + FT_STRING, BASE_NONE, NULL, 0x0, + "String containing the serial number of the device", HFILL + } }, + + { &hf_u3v_bootstrap_User_Defined_Name, + { "User Defined Name", "u3v.bootstrap.User_Defined_Name", + FT_STRING, BASE_NONE, NULL, 0x0, + "String containing the user defined name of the device", HFILL + } }, + + { &hf_u3v_bootstrap_Device_Capability, + { "Device Capabilities", "u3v.bootstrap.Device_Capability", + FT_UINT64, BASE_DEC, NULL, 0x0, + "Bit field describing the device?s capabilities", HFILL + } }, + + { &hf_u3v_bootstrap_Maximum_Device_Response_Time, + { "Device Maximum response time in ms", "u3v.bootstrap.Maximum_Device_Response_Time", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Maximum response time in ms", HFILL + } }, + + { &hf_u3v_bootstrap_Manifest_Table_Address, + { "Pointer to the Manifest Table", "u3v.bootstrap.Manifest_Table_Address", + FT_UINT64, BASE_HEX, NULL, 0x0, + NULL, HFILL + } }, + + { &hf_u3v_bootstrap_SBRM_Address, + { "Pointer to the SBRM", "u3v.bootstrap.SBRM_Address", + FT_UINT64, BASE_HEX, NULL, 0x0, + "Pointer to the Technology Specific Bootstrap Register Map", HFILL + } }, + + { &hf_u3v_bootstrap_Device_Configuration, + { "Device Configuration", "u3v.bootstrap.Device_Configuration", + FT_UINT64, BASE_DEC, NULL, 0x0, + "Bit field describing the device?s configuration", HFILL + } }, + + { &hf_u3v_bootstrap_Heartbeat_Timeout, + { "Heartbeat Timeout in ms.", "u3v.bootstrap.Heartbeat_Timeout", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Heartbeat Timeout in ms. Not used for these specification.", HFILL + } }, + + { &hf_u3v_bootstrap_Message_Channel_channel_id, + { "Message channel id", "u3v.bootstrap.Message_Channel_channel_id", + FT_UINT32, BASE_DEC, NULL, 0x0, + "channel_id use for the message channel", HFILL + } }, + + { &hf_u3v_bootstrap_Timestamp, + { "Timestamp", "u3v.bootstrap.Timestamp", + FT_UINT64, BASE_DEC, NULL, 0x0, + "Current device time in ns", HFILL + } }, + + { &hf_u3v_bootstrap_Timestamp_Latch, + { "Latch Timestamp", "u3v.bootstrap.Timestamp_Latch", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Timestamp Latch", HFILL + } }, + + { &hf_u3v_bootstrap_Timestamp_Increment, + { "Timestamp Increment Value", "u3v.bootstrap.Timestamp_Increment", + FT_UINT64, BASE_DEC, NULL, 0x0, + "Timestamp Increment", HFILL + } }, + + { &hf_u3v_bootstrap_Access_Privilege, + { "Access Privilege.", "u3v.bootstrap.Access_Privilege", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Access Privilege. Not used for these specification.", HFILL + } }, + + { &hf_u3v_bootstrap_Protocol_Endianess, + { "Protocol Endianess", "u3v.bootstrap.Protocol_Endianess", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Endianess of protocol fields and bootstrap registers. Only little endian is supported by these specification.", HFILL + } }, + + { &hf_u3v_bootstrap_Implementation_Endianess, + { "Device Endianess", "u3v.bootstrap.Implementation_Endianess", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Endianess of device implementation registers. Only little endian is supported by these specification.", HFILL + } }, + + { &hf_u3v_bootstrap_U3V_Version, + { "TL Version", "u3v.bootstrap.U3V_Version", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Version of the TL specification", HFILL + } }, + + { &hf_u3v_bootstrap_U3VCP_Capability_Register, + { "Control channel capabilities", "u3v.bootstrap.U3VCP_Capability_Register", + FT_UINT64, BASE_DEC, NULL, 0x0, + "Indicates additional features on the control channel", HFILL + } }, + + { &hf_u3v_bootstrap_U3VCP_Configuration_Register, + { "Control channel configuration", "u3v.bootstrap.U3VCP_Configuration_Register", + FT_UINT64, BASE_DEC, NULL, 0x0, + "Configures additional features on the control channel", HFILL + } }, + + { &hf_u3v_bootstrap_Maximum_Command_Transfer_Length, + { "Maximum Command Transfer Length", "u3v.bootstrap.Maximum_Command_Transfer_Length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Specifies the maximum supported command transfer length of the device", HFILL + } }, + + { &hf_u3v_bootstrap_Maximum_Acknowledge_Transfer_Length, + { "Maximum Acknowledge Transfer Length", "u3v.bootstrap.Maximum_Acknowledge_Transfer_Length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Specifies the maximum supported acknowledge transfer length of the device", HFILL + } }, + + { &hf_u3v_bootstrap_Number_of_Stream_Channels, + { "Number of Stream Channels", "u3v.bootstrap.Number_of_Stream_Channels", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Number of Stream Channels and its corresponding Streaming Interface Register Maps (SIRM)", HFILL + } }, + + { &hf_u3v_bootstrap_SIRM_Address, + { "Pointer to the first SIRM", "u3v.bootstrap.SIRM_Address", + FT_UINT64, BASE_HEX, NULL, 0x0, + "Pointer to the first Streaming Interface Register Map.", HFILL + } }, + + { &hf_u3v_bootstrap_SIRM_Length, + { "Length of SIRM", "u3v.bootstrap.SIRM_Length", + FT_UINT32, BASE_HEX, NULL, 0x0, + "Specifies the length of each SIRM", HFILL + } }, + + { &hf_u3v_bootstrap_EIRM_Address, + { "Pointer to the EIRM", "u3v.bootstrap.EIRM_Address", + FT_UINT64, BASE_HEX, NULL, 0x0, + "Pointer to the Event Interface Register Map.", HFILL + } }, + + { &hf_u3v_bootstrap_EIRM_Length, + { "Length of EIRM", "u3v.bootstrap.EIRM_Length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Specifies the length of the EIRM", HFILL + } }, + + { &hf_u3v_bootstrap_IIDC2_Address, + { "Pointer to the IIDC2", "u3v.bootstrap.IIDC2_Address", + FT_UINT64, BASE_HEX, NULL, 0x0, + "Pointer to the IIDC2 register set.", HFILL + } }, + + { &hf_u3v_bootstrap_Current_Speed, + { "LinkSpeed", "u3v.bootstrap.Current_Speed", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Specifies the current speed of the USB link.", HFILL + } }, + + { &hf_u3v_bootstrap_SI_Info, + { "Stream Info", "u3v.bootstrap.SI_Info", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Device reports information about stream interface", HFILL + } }, + + { &hf_u3v_bootstrap_SI_Control, + { "Stream Control", "u3v.bootstrap.SI_Control", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Stream interface Operation Control", HFILL + } }, + + { &hf_u3v_bootstrap_SI_Required_Payload_Size, + { "Stream Max Required Payload Size", "u3v.bootstrap.SI_Required_Payload_Size", + FT_UINT64, BASE_DEC, NULL, 0x0, + "Device reports maximum payload size with current settings", HFILL + } }, + + { &hf_u3v_bootstrap_SI_Required_Leader_Size, + { "Stream Max Required Leader Size", "u3v.bootstrap.SI_Required_Leader_Size", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Device reports maximum leader size it will use", HFILL + } }, + + { &hf_u3v_bootstrap_SI_Required_Trailer_Size, + { "Stream Max Required Trailer Size", "u3v.bootstrap.SI_Required_Trailer_Size", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Device reports maximum trailer size it will use", HFILL + } }, + + { &hf_u3v_bootstrap_SI_Maximum_Leader_Size, + { "Stream Max leader size", "u3v.bootstrap.SI_Maximum_Leader_Size", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Maximum leader size", HFILL + } }, + + { &hf_u3v_bootstrap_SI_Payload_Transfer_Size, + { "Stream transfer size", "u3v.bootstrap.SI_Payload_Transfer_Size", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Expected Size of a single Payload Transfer", HFILL + } }, + + { &hf_u3v_bootstrap_SI_Payload_Transfer_Count, + { "Stream transfer count", "u3v.bootstrap.SI_Payload_Transfer_Count", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Expected Number of Payload Transfers", HFILL + } }, + + { &hf_u3v_bootstrap_SI_Payload_Final_Transfer1_Size, + { "Stream final transfer 1 size", "u3v.bootstrap.SI_Payload_Final_Transfer1_Size", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Size of first final Payload transfer", HFILL + } }, + + { &hf_u3v_bootstrap_SI_Payload_Final_Transfer2_Size, + { "Stream final transfer 2 size", "u3v.bootstrap.SI_Payload_Final_Transfer2_Size", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Size of second final Payload transfer", HFILL + } }, + + { &hf_u3v_bootstrap_SI_Maximum_Trailer_Size, + { "Stream Max trailer size", "u3v.bootstrap.SI_Maximum_Trailer_Size", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Maximum trailer size", HFILL + } }, + + { &hf_u3v_bootstrap_EI_Control, + { "Event Interface Control", "u3v.bootstrap.EI_Control", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Event Interface Control Register", HFILL + } }, + + { &hf_u3v_bootstrap_Maximum_Event_Transfer_Length, + { "Event max Transfer size", "u3v.bootstrap.Maximum_Event_Transfer_Length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Specifies the maximum supported event command transfer length of the device.", HFILL + } }, + + { &hf_u3v_bootstrap_Event_Test_Control, + { "Event test event control", "u3v.bootstrap.Event_Test_Control", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Control the generation of test events.", HFILL + } }, + + { &hf_u3v_stream_prefix, + { "Stream Prefix", "u3v.stream.prefix", + FT_UINT32, BASE_HEX, NULL, 0, + "U3V stream prefix", HFILL + } }, + + { &hf_u3v_stream_reserved, + { "Reserved", "u3v.stream.reserved", + FT_BYTES, BASE_NONE, NULL, 0, + NULL, HFILL + } }, + + { &hf_u3v_stream_leader_size, + { "Leader Size", "u3v.stream.leader_size", + FT_UINT16, BASE_DEC, NULL, 0x0, + "U3V stream leader size", HFILL + } }, + + { &hf_u3v_stream_trailer_size, + { "Trailer Size", "u3v.stream.trailer_size", + FT_UINT16, BASE_DEC, NULL, 0x0, + "U3V stream trailer size", HFILL + } }, + + { &hf_u3v_stream_block_id, + { "Block ID", "u3v.stream.block_id", + FT_UINT64, BASE_DEC, NULL, 0x0, + "U3V stream block id", HFILL + } }, + + { &hf_u3v_stream_payload_type, + { "Payload Type", "u3v.stream.payload_type", + FT_UINT16, BASE_HEX, VALS( payload_type_names ), 0x0, + "U3V Payload Type", HFILL + } }, + + { &hf_u3v_stream_timestamp, + { "Timestamp", "u3v.stream.timestamp", + FT_UINT64, BASE_HEX_DEC, NULL, 0x0, + "U3V Stream Timestamp", HFILL + } }, + + { &hf_u3v_stream_pixel_format, + { "Pixel Format", "u3v.stream.pixel_format", + FT_UINT32, BASE_HEX|BASE_EXT_STRING, VALS_EXT_PTR( &pixel_format_names_ext ), 0x0, + "U3V Stream Pixel Format", HFILL + } }, + + { &hf_u3v_stream_size_x, + { "Size X", "u3v.stream.sizex", + FT_UINT32, BASE_DEC, NULL, 0x0, + "U3V Stream Size X", HFILL + } }, + + { &hf_u3v_stream_size_y, + { "Size Y", "u3v.stream.sizey", + FT_UINT32, BASE_DEC, NULL, 0x0, + "U3V Stream Size Y", HFILL + } }, + + { &hf_u3v_stream_offset_x, + { "Offset X", "u3v.stream.offsetx", + FT_UINT32, BASE_DEC, NULL, 0x0, + "U3V Stream Offset X", HFILL + } }, + + { &hf_u3v_stream_offset_y, + { "Offset Y", "u3v.stream.offsety", + FT_UINT32, BASE_DEC, NULL, 0x0, + "U3V Stream Offset Y", HFILL + } }, + + { &hf_u3v_stream_padding_x, + { "Padding X", "u3v.stream.paddingx", + FT_UINT16, BASE_DEC, NULL, 0x0, + "U3V Stream Padding X", HFILL + } }, + + { &hf_u3v_stream_chunk_layout_id, + { "Chunk Layout ID", "u3v.stream.chunk_layout_id", + FT_UINT32, BASE_HEX, NULL, 0x0, + "U3V Stream Chunk Layout ID", HFILL + } }, + + { &hf_u3v_stream_valid_payload_size, + { "Valid Payload Size", "u3v.stream.valid_payload_size", + FT_UINT64, BASE_HEX, NULL, 0x0, + "U3V Stream Valid Payload Size", HFILL + } }, + + { &hf_u3v_stream_status, + { "Status", "u3v.stream.status", + FT_UINT16, BASE_HEX, VALS( status_names ), 0x0, + "U3V Stream Status", HFILL + } }, + + { &hf_u3v_stream_data, + { "Payload Data", "u3v.stream.data", + FT_BYTES, BASE_NONE, NULL, 0x0, + "U3V Stream Payload Data", HFILL + } }, + + /* U3V device info descriptor */ + { &hf_u3v_device_info_descriptor_bLength, + { "bLength", "u3v.device_info.bLength", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_bDescriptorType, + { "bDescriptorType", "u3v.device_info.bDescriptorType", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_bDescriptorSubtype, + { "bDescriptorSubtype", "u3v.device_info.bDescriptorSubtype", + FT_UINT8, BASE_HEX, VALS( u3v_descriptor_subtypes ), 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_bGenCPVersion, + { "bGenCPVersion", "u3v.device_info.bGenCPVersion", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_bGenCPVersion_minor, + { "Minor Version", "u3v.device_info.bGenCPVersion.minor", + FT_UINT32, BASE_DEC, NULL, 0x0000FFFF, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_bGenCPVersion_major, + { "Major Version", "u3v.device_info.bGenCPVersion.major", + FT_UINT32, BASE_DEC, NULL, 0xFFFF0000, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_bU3VVersion, + { "bU3VVersion", "u3v.device_info.bU3VVersion", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_bU3VVersion_minor, + { "Minor Version", "u3v.device_info.bU3VVersion.minor", + FT_UINT32, BASE_DEC, NULL, 0x0000FFFF, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_bU3VVersion_major, + { "Major Version", "u3v.device_info.bU3VVersion.major", + FT_UINT32, BASE_DEC, NULL, 0xFFFF0000, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_iDeviceGUID, + { "iDeviceGUID", "u3v.device_info.iDeviceGUID", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_iVendorName, + { "iVendorName", "u3v.device_info.iVendorName", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_iModelName, + { "iModelName", "u3v.device_info.iModelName", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_iFamilyName, + { "iFamilyName", "u3v.device_info.iFamilyName", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_iDeviceVersion, + { "iDeviceVersion", "u3v.device_info.iDeviceVersion", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_iManufacturerInfo, + { "iManufacturerInfo", "u3v.device_info.iManufacturerInfo", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_iSerialNumber, + { "iSerialNumber", "u3v.device_info.iSerialNumber", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_iUserDefinedName, + { "iVendorName", "u3v.device_info.iUserDefinedName", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_bmSpeedSupport, + { "bmSpeedSupport", "u3v.device_info.bmSpeedSupport", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_bmSpeedSupport_low_speed, + { "Low-Speed", "u3v.device_info.bmSpeedSupport.lowSpeed", + FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x01, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_bmSpeedSupport_full_speed, + { "Full-Speed", "u3v.device_info.bmSpeedSupport.fullSpeed", + FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x02, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_bmSpeedSupport_high_speed, + { "High-Speed", "u3v.device_info.bmSpeedSupport.highSpeed", + FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x04, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_bmSpeedSupport_super_speed, + { "Super-Speed", "u3v.device_info.bmSpeedSupport.superSpeed", + FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x08, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor_bmSpeedSupport_reserved, + { "Reserved", "u3v.device_info.bmSpeedSupport.reserved", + FT_UINT8, BASE_HEX, NULL, 0xF0, + NULL, HFILL } }, + + { &hf_u3v_scd_readmem_cmd, + { "SCD: READMEM_CMD", "u3v.scd_readmem_cmd", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_scd_writemem_cmd, + { "SCD: WRITEMEM_CMD", "u3v.scd_writemem_cmd", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_scd_event_cmd, + { "SCD: EVENT_CMD", "u3v.scd_event_cmd", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_scd_ack_readmem_ack, + { "SCD: READMEM_ACK", "u3v.scd_ack_readmem_ack", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_scd_writemem_ack, + { "SCD: WRITEMEM_ACK", "u3v.scd_writemem_ack", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_ccd_pending_ack, + { "CCD: PENDING_ACK", "u3v.ccd_pending_ack", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_stream_leader, + { "Stream: Leader", "u3v.stream_leader", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_stream_trailer, + { "Stream: Trailer", "u3v.stream_trailer", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_stream_payload, + { "Stream: Payload", "u3v.stream_payload", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_ccd_cmd, + { "CCD", "u3v.ccd_cmd", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_ccd_ack, + { "CCD", "u3v.ccd_ack", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_u3v_device_info_descriptor, + { "U3V DEVICE INFO DESCRIPTOR", "u3v.device_info_descriptor", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } } +}; + +void +proto_register_u3v(void) +{ + static gint *ett[] = { + &ett_u3v, + &ett_u3v_cmd, + &ett_u3v_flags, + &ett_u3v_ack, + &ett_u3v_payload_cmd, + &ett_u3v_payload_ack, + &ett_u3v_payload_ack_subtree, + &ett_u3v_payload_cmd_subtree, + &ett_u3v_bootstrap_fields, + &ett_u3v_stream_leader, + &ett_u3v_stream_trailer, + &ett_u3v_stream_payload, + &ett_u3v_device_info_descriptor, + &ett_u3v_device_info_descriptor_speed_support, + &ett_u3v_device_info_descriptor_gencp_version, + &ett_u3v_device_info_descriptor_u3v_version, + }; + + proto_u3v = proto_register_protocol("USB 3 Vision", "U3V", "u3v"); + proto_register_field_array(proto_u3v, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + register_dissector("u3v", dissect_u3v, proto_u3v); +} + + + +void +proto_reg_handoff_u3v(void) +{ + dissector_handle_t u3v_handle = NULL; + dissector_handle_t u3v_descr_handle = NULL; + + u3v_handle = find_dissector("u3v"); + dissector_add_uint("usb.bulk", IF_CLASS_MISCELLANEOUS, u3v_handle); + heur_dissector_add("usb.bulk", dissect_u3v_heur, "USB3Vision Protocol", "u3v", proto_u3v,HEURISTIC_ENABLE); + u3v_descr_handle = create_dissector_handle(dissect_u3v_descriptors, proto_u3v); + dissector_add_uint("usb.descriptor", IF_CLASS_MISCELLANEOUS, u3v_descr_handle); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ |