44#ifndef QC_RADAR_EXT_IFACE_HPP
55#define QC_RADAR_EXT_IFACE_HPP
66
7+ #include < stdint.h>
8+
9+ // ---------------------------------------------------------------------------
10+ // Platform-specific includes — must be outside any namespace
11+ // ---------------------------------------------------------------------------
12+ #ifndef __linux__
713#include < devctl.h>
814#include < fcntl.h>
9- #include < iostream>
1015#include < sys/iofunc.h>
1116#include < sys/neutrino.h>
1217#include < unistd.h>
13-
14- // For debug
18+ #else
19+ #include < cerrno>
20+ #include < cstdio>
1521#include < cstring>
22+ #include < string>
23+ #include < sys/socket.h>
24+ #include < sys/un.h>
25+ #include < unistd.h>
26+ #endif
27+
28+ // ---------------------------------------------------------------------------
29+ // Protocol wire types — always defined on all platforms
30+ // ---------------------------------------------------------------------------
31+
32+ #pragma pack( push, 1 )
33+ typedef struct RadarMsgHeader
34+ {
35+ uint32_t magic; // 0x52414452 = 'RADR'
36+ uint16_t version; // 1
37+ uint16_t msg_type; // 1=req_dma, 2=resp
38+ uint32_t payload_len; // bytes after this header
39+ uint32_t request_id; // client-generated correlation id
40+ } RadarMsgHeader_t;
41+
42+ typedef struct RadarReqDmaBuf
43+ {
44+ size_t input_size;
45+ size_t output_max;
46+ uint32_t flags;
47+ uint32_t timeout_ms;
48+ } RadarReqDmaBuf_t;
49+
50+ typedef struct RadarResp
51+ {
52+ int32_t status;
53+ uint32_t output_size;
54+ uint32_t flags;
55+ } RadarResp_t;
56+ #pragma pack( pop )
1657
1758namespace q
1859{
1960namespace interface
2061{
2162
22- constexpr int DCMD_EXECUTE_CMD_IOV = __DIOT( _DCMD_MISC, 2 , 0xFFu );
63+ static constexpr uint32_t RADAR_MAGIC = 0x52414452u ; // 'RADR'
64+ static constexpr uint16_t RADAR_PROTO_VERSION = 1 ;
65+ static constexpr uint16_t RADAR_MSG_REQ_DMA = 1 ;
66+ static constexpr uint16_t RADAR_MSG_RESP = 2 ;
67+ static constexpr uint32_t RADAR_FLAG_INPUT_FD = ( 1u << 0 );
68+ static constexpr uint32_t RADAR_FLAG_OUTPUT_FD = ( 1u << 1 );
69+ static constexpr uint32_t RADAR_FLAG_OUT_OWNABLE = ( 1u << 2 );
70+
71+ // Return sentinels used by both platforms (0 = success, negative = error)
72+ static constexpr int RADAR_OK = 0 ;
73+ static constexpr int RADAR_ETIMEOUT = -1 ;
74+ static constexpr int RADAR_EINVAL = -2 ;
75+ static constexpr int RADAR_EPROTO = -3 ;
76+
77+ // ---------------------------------------------------------------------------
78+ // QNX transport (devctl)
79+ // ---------------------------------------------------------------------------
80+ #ifndef __linux__
81+
82+ typedef struct CommandExecute
83+ {
84+ uint64_t input_handle;
85+ uint64_t output_handle;
86+ size_t input_size;
87+ size_t output_size;
88+ } CommandExecute_t;
89+
90+ constexpr int DCMD_EXECUTE_CMD = __DIOT( _DCMD_MISC, 1 , CommandExecute_t );
2391
2492class Radar
2593{
2694public:
27- Radar ( const char *device ) { fd = open ( device, O_RDWR ); }
95+ Radar ( const char *device, uint32_t /* timeoutMs*/ = 5000 ) { m_fd = open ( device, O_RDWR ); }
96+
97+ bool IsOpen () const { return m_fd != -1 ; }
98+
99+ ~Radar () { close ( m_fd ); }
100+
101+ Radar ( const Radar & ) = delete ;
102+ Radar &operator =( const Radar & ) = delete ;
103+ Radar ( Radar && ) = delete ;
104+ Radar &operator =( Radar && ) = delete ;
105+
106+ int Execute ( uint64_t input_handle, size_t input_size, uint64_t output_handle,
107+ size_t output_size )
108+ {
109+ CommandExecute_t cmd{};
110+ cmd.input_handle = input_handle;
111+ cmd.output_handle = output_handle;
112+ cmd.input_size = input_size;
113+ cmd.output_size = output_size;
114+ int ret = devctl ( m_fd, DCMD_EXECUTE_CMD , &cmd, sizeof ( cmd ), NULL );
115+ return ret;
116+ }
28117
29- bool is_open () const { return fd != -1 ; }
118+ private:
119+ int m_fd;
120+ };
30121
31- ~Radar () { close ( fd ); }
122+ // ---------------------------------------------------------------------------
123+ // Linux transport (AF_UNIX SOCK_SEQPACKET + SCM_RIGHTS)
124+ // ---------------------------------------------------------------------------
125+ #else
32126
33- int execute ( uint8_t *pinput, size_t input_size, uint8_t *poutput, size_t output_size )
127+ class Radar
128+ {
129+ public:
130+ Radar ( const char *device, uint32_t timeoutMs = 5000 ) : m_timeoutMs( timeoutMs )
34131 {
35- iov_t tx;
36- iov_t rx;
37- SETIOV ( &tx, pinput, input_size );
38- SETIOV ( &rx, poutput, output_size );
39- int status = devctlv ( fd, DCMD_EXECUTE_CMD_IOV , 1 , 1 , &tx, &rx, NULL );
40- if ( status != EOK )
132+ m_sockfd = socket ( AF_UNIX , SOCK_SEQPACKET , 0 );
133+ if ( m_sockfd != -1 )
41134 {
42- return status;
135+ struct sockaddr_un addr
136+ {
137+ };
138+ addr.sun_family = AF_UNIX ;
139+ strncpy ( addr.sun_path , device, sizeof ( addr.sun_path ) - 1 );
140+ int ret = connect ( m_sockfd, reinterpret_cast <struct sockaddr *>( &addr ),
141+ sizeof ( addr ) );
142+ if ( ret == -1 )
143+ {
144+ close ( m_sockfd );
145+ m_sockfd = -1 ;
146+ }
147+ else
148+ {
149+ struct timeval tv
150+ {
151+ };
152+ tv.tv_sec = timeoutMs / 1000 ;
153+ tv.tv_usec = ( timeoutMs % 1000 ) * 1000 ;
154+ setsockopt ( m_sockfd, SOL_SOCKET , SO_RCVTIMEO , &tv, sizeof ( tv ) );
155+ }
156+ }
157+ }
158+
159+ bool IsOpen () const { return m_sockfd != -1 ; }
160+
161+ ~Radar ()
162+ {
163+ if ( m_sockfd != -1 )
164+ {
165+ close ( m_sockfd );
166+ }
167+ }
168+
169+ Radar ( const Radar & ) = delete ;
170+ Radar &operator =( const Radar & ) = delete ;
171+ Radar ( Radar && ) = delete ;
172+ Radar &operator =( Radar && ) = delete ;
173+
174+ int Execute ( uint64_t input_handle, size_t input_size, uint64_t output_handle,
175+ size_t output_size )
176+ {
177+ int returnCode = RADAR_OK ;
178+ int input_fd = static_cast <int >( input_handle );
179+ int output_fd = static_cast <int >( output_handle );
180+ uint32_t req_id = ++m_requestId;
181+
182+ RadarMsgHeader_t hdr{};
183+ hdr.magic = RADAR_MAGIC ;
184+ hdr.version = RADAR_PROTO_VERSION ;
185+ hdr.msg_type = RADAR_MSG_REQ_DMA ;
186+ hdr.payload_len = sizeof ( RadarReqDmaBuf_t );
187+ hdr.request_id = req_id;
188+
189+ RadarReqDmaBuf_t req{};
190+ req.input_size = input_size;
191+ req.output_max = output_size;
192+ req.flags = RADAR_FLAG_INPUT_FD | RADAR_FLAG_OUTPUT_FD | RADAR_FLAG_OUT_OWNABLE ;
193+ req.timeout_ms = m_timeoutMs;
194+
195+ struct iovec iov[2 ];
196+ iov[0 ].iov_base = &hdr;
197+ iov[0 ].iov_len = sizeof ( hdr );
198+ iov[1 ].iov_base = &req;
199+ iov[1 ].iov_len = sizeof ( req );
200+
201+ int fds[2 ] = { input_fd, output_fd };
202+ char cmsg_buf[CMSG_SPACE ( sizeof ( fds ) )];
203+ memset ( cmsg_buf, 0 , sizeof ( cmsg_buf ) );
204+
205+ struct msghdr msg
206+ {
207+ };
208+ msg.msg_iov = iov;
209+ msg.msg_iovlen = 2 ;
210+ msg.msg_control = cmsg_buf;
211+ msg.msg_controllen = sizeof ( cmsg_buf );
212+
213+ struct cmsghdr *cmsg = CMSG_FIRSTHDR ( &msg );
214+ cmsg->cmsg_level = SOL_SOCKET ;
215+ cmsg->cmsg_type = SCM_RIGHTS ;
216+ cmsg->cmsg_len = CMSG_LEN ( sizeof ( fds ) );
217+ memcpy ( CMSG_DATA ( cmsg ), fds, sizeof ( fds ) );
218+
219+ ssize_t ret = sendmsg ( m_sockfd, &msg, 0 );
220+ if ( ret != -1 )
221+ {
222+ returnCode = RecvResponse ( req_id );
43223 }
44224 else
45225 {
46- return EOK ;
226+ returnCode = RADAR_EPROTO ;
47227 }
228+
229+ return returnCode;
48230 }
49231
50232private:
51- int fd;
233+ int RecvResponse ( uint32_t expected_req_id )
234+ {
235+ RadarMsgHeader_t resp_hdr{};
236+ RadarResp_t resp{};
237+
238+ struct iovec iov[2 ];
239+ iov[0 ].iov_base = &resp_hdr;
240+ iov[0 ].iov_len = sizeof ( resp_hdr );
241+ iov[1 ].iov_base = &resp;
242+ iov[1 ].iov_len = sizeof ( resp );
243+
244+ struct msghdr msg
245+ {
246+ };
247+ msg.msg_iov = iov;
248+ msg.msg_iovlen = 2 ;
249+
250+ int returnCode;
251+
252+ ssize_t n = recvmsg ( m_sockfd, &msg, 0 );
253+ if ( n == -1 )
254+ {
255+ if ( errno == EAGAIN || errno == EWOULDBLOCK )
256+ {
257+ returnCode = RADAR_ETIMEOUT ;
258+ }
259+ else
260+ {
261+ returnCode = RADAR_EPROTO ;
262+ }
263+ }
264+ else if ( n < static_cast <ssize_t >( sizeof ( resp_hdr ) + sizeof ( resp ) ) )
265+ {
266+ returnCode = RADAR_EPROTO ;
267+ }
268+ else if ( resp_hdr.magic != RADAR_MAGIC || resp_hdr.version != RADAR_PROTO_VERSION )
269+ {
270+ returnCode = RADAR_EPROTO ;
271+ }
272+ else if ( resp_hdr.request_id != expected_req_id )
273+ {
274+ returnCode = RADAR_EPROTO ;
275+ }
276+ else if ( resp_hdr.msg_type != RADAR_MSG_RESP )
277+ {
278+ returnCode = RADAR_EPROTO ;
279+ }
280+ else if ( resp.status == 0 )
281+ {
282+ returnCode = RADAR_OK ;
283+ }
284+ else if ( resp.status == -ETIMEDOUT )
285+ {
286+ returnCode = RADAR_ETIMEOUT ;
287+ }
288+ else if ( resp.status == -EINVAL )
289+ {
290+ returnCode = RADAR_EINVAL ;
291+ }
292+ else
293+ {
294+ returnCode = RADAR_EPROTO ;
295+ }
296+
297+ return returnCode;
298+ }
299+
300+ int m_sockfd = -1 ;
301+ uint32_t m_requestId = 0 ;
302+ uint32_t m_timeoutMs;
303+ std::string m_sockPath;
52304};
53305
306+ #endif // __linux__
54307
55308} // namespace interface
56309} // namespace q
57310
58- #endif // QC_RADAR_EXT_IFACE_HPP
311+ #endif // QC_RADAR_EXT_IFACE_HPP
0 commit comments