1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//! # XVC Server Library
//!
//! This crate provides a foundation for implementing Xilinx Virtual Cable (XVC) servers
//! that handle JTAG communication with FPGA devices over network connections.
//!
//! ## Overview
//!
//! XVC is a protocol used by Xilinx design tools to interact with FPGA devices remotely.
//! This library abstracts the protocol handling and provides a server implementation that
//! can work with different backend device drivers.
//!
//! ## Architecture
//!
//! The crate is built around two main components:
//!
//! - **[`XvcServer`] Trait**: Defines the interface that backend drivers must implement
//! to handle low-level JTAG operations (TCK configuration and vector shifting)
//! - **[`server::Server`]**: A generic server that handles XVC protocol communication,
//! message parsing, and client connections
//!
//! ## How It Works
//!
//! 1. A backend driver (e.g., kernel driver, UIO device) implements the [`XvcServer`] trait
//! 2. The driver is wrapped in a [`server::Server`] instance
//! 3. The server listens for TCP connections and processes XVC protocol messages
//! 4. Each message is dispatched to the backend driver for actual JTAG operations
//! 5. Results are serialized and sent back to the client
//!
//! ## Protocol Support
//!
//! This implementation supports the XVC 1.0 protocol with the following operations:
//!
//! - **GetInfo**: Query server capabilities (version, max vector size)
//! - **SetTck**: Configure the JTAG Test Clock (TCK) period
//! - **Shift**: Perform JTAG vector shifting (TMS/TDI/TDO)
//!
//! For detailed protocol information, see the [`xvc_protocol`](https://docs.rs/xvc-protocol/) crate.
//!
//! ## Basic Usage
//!
//! ### Implementing a Backend Driver
//!
//! Create a struct that implements the [`XvcServer`] trait:
//!
//! ```no_run
//! use xvc_server::XvcServer;
//!
//! struct MyDriver {
//! // device-specific fields
//! }
//!
//! impl XvcServer for MyDriver {
//! type Err = std::io::Error; // device-specific error
//!
//! fn set_tck(&self, period_ns: u32) -> Result<u32, Self::Err> {
//! // Configure hardware TCK period
//! Ok(period_ns)
//! }
//!
//! fn shift(&self, num_bits: u32, tms: &[u8], tdi: &[u8], tdo: &mut [u8]) -> Result<(), Self::Err> {
//! // Perform JTAG shifting and write the captured TDO data to `tdo`
//! Ok(())
//! }
//! }
//! ```
//!
//! ### Starting the Server
//!
//! ```ignore
//! use xvc_server::server::{Server, Config};
//! use std::net::{IpAddr, Ipv4Addr, SocketAddr};
//!
//! let driver = MyDriver::new()?;
//! let config = Config::default();
//! let server = Server::new(driver, config);
//!
//! let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 2542);
//! server.listen(addr).await?;
//! ```
//!
//! ## Error Handling
//!
//! The XVC 1.0 protocol specification does not support error reporting in the Shift operation.
//!
//! ## Configuration
//!
//! Server behavior can be customized via [`server::Config`]:
//!
//! - **max_vector_size**: Maximum size of JTAG vectors (default: 10 MiB)
//! - **read_write_timeout**: Socket I/O timeout duration (default: 30 seconds)
//!
//! ## Logging
//!
//! This crate uses the `log` crate for diagnostics. Enable logging to see:
//! - Client connections and disconnections
//! - Protocol messages being processed
//! - Configuration details and error conditions
//!
//! Configure logging with an implementation like `env_logger`:
//!
//! ```ignore
//! env_logger::init();
//! ```
//!
//! ## Thread Model
//!
//! The server is async (tokio) and accepts connections concurrently, but enforces
//! **at-most-one active client** at a time. A second connection attempt while a client
//! is active is immediately rejected. This matches the XVC protocol assumption of a
//! single JTAG session and prevents interleaved access to the hardware state machine.
//!
//! Backend methods (`set_tck`, `shift`) are called via `block_in_place`, so the server
//! requires a multi-thread tokio runtime.
/// Trait that backend drivers must implement to provide JTAG functionality.
///
/// This trait defines the interface between the XVC protocol server and the actual
/// hardware debug bridge driver. Implementors are responsible for translating
/// high-level JTAG operations into hardware-specific commands.
///
/// See the [`xvc-server-debugbridge`](https://docs.rs/xvc-server-debugbridge/) crate for examples.