23
23
*
24
24
*/
25
25
26
+ #include <ocac/ocp/ocp1.h>
27
+ #include <ocac/obj.h>
28
+ #include <ocac/occ/datatypes/framework.h>
26
29
#include "ocac/core.h"
27
30
28
31
#include "ocac/session.h"
29
32
33
+
34
+ extern OCAC_OBJ_BASE * ocac_obj_registry_get (OcaONo ono );
35
+
36
+
30
37
void ocac_core_init ()
31
38
{
32
39
ocac_session_init ();
@@ -38,7 +45,7 @@ void ocac_core_deinit()
38
45
}
39
46
40
47
41
- void ocac_core_rx_packet (struct ocac_sock * sock , u8_t * inbuf , u16_t inlen , u8_t * outbuf , u16_t maxoutlen )
48
+ void ocac_core_rx_packet (struct ocac_sock * sock , u8_t * inbuf , u32_t inlen , u8_t * outbuf , u32_t maxoutlen )
42
49
{
43
50
OCAC_ASSERT ("sock != NULL" , sock != NULL );
44
51
OCAC_ASSERT ("OCAC_NET_TYPE_ISVALID(sock->type)" , OCAC_NET_TYPE_ISVALID (sock -> type ));
@@ -83,12 +90,12 @@ void ocac_core_rx_packet(struct ocac_sock * sock, u8_t * inbuf, u16_t inlen, u8_
83
90
84
91
85
92
// read out PDU header
86
- Ocp1Header header ;
93
+ Ocp1Header inheader ;
87
94
88
- ocac_ocp1_header_read (& header , & inbuf [1 ]);
95
+ ocac_ocp1_header_read (& inheader , & inbuf [1 ]);
89
96
90
97
// check if actual packet length is equal to inbuffer length (+1 for syn byte)
91
- if (header .pduSize + 1 != inlen ){
98
+ if (inheader .pduSize + 1 != inlen ){
92
99
93
100
OCAC_DEBUGF (OCAC_DBG_TRACE | OCAC_DBG_LEVEL_WARNING , "Invalid packet length" );
94
101
@@ -97,18 +104,18 @@ void ocac_core_rx_packet(struct ocac_sock * sock, u8_t * inbuf, u16_t inlen, u8_
97
104
}
98
105
99
106
// messagecount must be at least 1
100
- if (header .messageCount == 0 ){
107
+ if (inheader .messageCount == 0 ){
101
108
102
109
OCAC_DEBUGF (OCAC_DBG_TRACE | OCAC_DBG_LEVEL_WARNING , "invalid message count" );
103
110
104
111
// (we could choose not to be so strict about it if the packet length is right)
105
112
return ;
106
113
}
107
114
108
- if (header .pduType == OcaMessageType_KeepAlive ){
115
+ if (inheader .pduType == OcaMessageType_KeepAlive ){
109
116
110
117
// heartbeat messages MUST have a message count of 1 ..
111
- if (header .messageCount != 1 ){
118
+ if (inheader .messageCount != 1 ){
112
119
113
120
OCAC_DEBUGF (OCAC_DBG_TRACE | OCAC_DBG_LEVEL_WARNING , "invalid message count" );
114
121
@@ -151,12 +158,73 @@ void ocac_core_rx_packet(struct ocac_sock * sock, u8_t * inbuf, u16_t inlen, u8_
151
158
return ;
152
159
}
153
160
161
+ if (inheader .pduType == OcaMessageType_Command || inheader .pduType == OcaMessageType_CommandNR ){
162
+
163
+ u32_t inpos = 1 + sizeof (Ocp1Header ); // sync byte + header
164
+ u32_t outpos = 1 + sizeof (Ocp1Header );
165
+
166
+ Ocp1Header outheader ;
167
+
168
+ ocac_memset ( & outheader , 0 , sizeof (Ocp1Header ));
169
+
170
+ for (u16_t i = 0 ; i < inheader .messageCount ; i ++ ){
171
+
172
+ // make sure the four first bytes of the message (denoting its total length) are there
173
+ if (inpos + 4 > inlen ){
174
+ OCAC_DEBUGF (OCAC_DBG_TRACE | OCAC_DBG_LEVEL_WARNING , "missing msg size" );
175
+ return ;
176
+ }
177
+
178
+ u32_t len = ocac_ntohl (* (u32_t * )& inbuf [inpos ]);
179
+
180
+ // make sure all bytes of the message are there
181
+ if (inpos + len > inlen ){
182
+ OCAC_DEBUGF (OCAC_DBG_TRACE | OCAC_DBG_LEVEL_WARNING , "missing msg data" );
183
+ return ;
184
+ }
185
+
186
+ Ocp1CommandRef command ;
187
+
188
+ ocac_ocp1_commandref_read (& command , & inbuf [inpos ]);
189
+
190
+ u32_t posbefore = outheader .pduSize ;
191
+
192
+ ocac_core_command_handler (& command , (inheader .pduType == OcaMessageType_Command ), & outbuf [outpos ], & outpos , maxoutlen , session );
193
+
194
+ // if the outpos changed, a response was written to outbuf
195
+ if (outpos != posbefore ){
196
+ outheader .messageCount ++ ;
197
+ }
198
+
199
+ inpos += len ;
200
+ }
201
+
202
+ // if outpos changed response data was written by the handler
203
+ if (outheader .messageCount > 0 ) {
204
+
205
+ // finalize header
206
+ outheader .pduSize = outpos ;
207
+ outheader .pduType = OcaMessageType_Response ;
208
+ outheader .protocolVersion = OCAC_OCA_VERSION ;
209
+
210
+ outbuf [0 ] = OCP_SYNC_VAL ;
211
+
212
+ //write header to outbuf
213
+ ocac_ocp1_header_write (& outbuf [1 ], & outheader );
214
+
215
+ // TX of outbuf
216
+ ocac_sock_tx (sock , outbuf , outheader .pduSize + 1 );
217
+ }
218
+
219
+ return ;
220
+ }
221
+
154
222
#if OCAC_USE_RESPONSE_HANDLER == 1
155
- if (header .pduType == OcaMessageType_Response ){
223
+ if (inheader .pduType == OcaMessageType_Response ){
156
224
157
225
u32_t pos = 1 + sizeof (Ocp1Header );
158
226
159
- for (u16_t i = 0 ; i < header .messageCount ; i ++ ){
227
+ for (u16_t i = 0 ; i < inheader .messageCount ; i ++ ){
160
228
161
229
// make sure the four first bytes of the message (denoting its total length) are there
162
230
if (pos + 4 > inlen ){
@@ -186,11 +254,11 @@ void ocac_core_rx_packet(struct ocac_sock * sock, u8_t * inbuf, u16_t inlen, u8_
186
254
#endif //OCAC_USE_RESPONSE_HANDLER == 1
187
255
188
256
#if OCAC_USE_NOTIFICATION_HANDLER == 1
189
- if (header .pduType == OcaMessageType_Notification ){
257
+ if (inheader .pduType == OcaMessageType_Notification ){
190
258
191
259
u32_t pos = 1 + sizeof (Ocp1Header );
192
260
193
- for (u16_t i = 0 ; i < header .messageCount ; i ++ ){
261
+ for (u16_t i = 0 ; i < inheader .messageCount ; i ++ ){
194
262
195
263
// make sure the four first bytes of the message (denoting its total length) are there
196
264
if (pos + 4 > inlen ){
@@ -224,6 +292,59 @@ void ocac_core_rx_packet(struct ocac_sock * sock, u8_t * inbuf, u16_t inlen, u8_
224
292
225
293
}
226
294
295
+ u8_t ocac_core_command_handler (Ocp1CommandRef * command , u8_t requirersp , u8_t * outbuf , u32_t * outlen , u32_t maxoutlen , struct ocac_session * session )
296
+ {
297
+ OCAC_ASSERT ("command != NULL" , command != NULL );
298
+ OCAC_ASSERT ("outbuf != NULL" , outbuf != NULL );
299
+ OCAC_ASSERT ("outlen != NULL" , outlen != NULL );
300
+
301
+
302
+ // if a response is required, make sure there is at least space for response meta data
303
+ if (requirersp != 0 && * outlen + sizeof (Ocp1Response ) < maxoutlen ){
304
+
305
+ OCAC_DEBUGF (OCAC_DBG_TRACE | OCAC_DBG_LEVEL_WARNING , "not enough space for msg" );
306
+
307
+ return 1 ;
308
+ }
309
+
310
+ Ocp1ResponseRef response ;
311
+
312
+ response .statusCode = OcaStatus_OK ;
313
+
314
+ // attempt to get the called object
315
+ OCAC_OBJ_BASE * obj = ocac_obj_registry_get (command -> targetONo );
316
+
317
+ if (obj == NULL ){
318
+ response .statusCode = OcaStatus_BadONo ;
319
+ response .responseSize = 0 ;
320
+ } else {
321
+ // note
322
+ // developers implementing class methods may intuitively assume that the passed buffer is the starting point
323
+ // for writing response data and that the outlen reference thus initially is zero.
324
+ // This assumption (which makes developing methods easier in the first place) should be true.
325
+
326
+ u32_t pos = * outlen + sizeof (Ocp1Response );
327
+ u32_t len = 0 ;
328
+ u32_t max = maxoutlen - pos ;
329
+
330
+ // call class method on object
331
+ // note: response data is written directly to outbuf
332
+ response .statusCode = ocac_obj_exec (obj , command -> methodID .DefLevel , command -> methodID .MethodIndex , command -> parameters .parameters , command -> parameters .parameterCount , & outbuf [pos ], & len , max , session );
333
+
334
+ response .responseSize = len ;
335
+ }
336
+
337
+ // write response header if either required, there is response data or the command failed
338
+ if (requirersp != 0 || response .responseSize > 0 || response .statusCode != OcaStatus_OK ){
339
+
340
+ response .responseSize += sizeof (Ocp1Response );
341
+ response .handle = command -> handle ;
342
+
343
+ ocac_ocp1_responseref_write (outbuf , & response );
344
+ }
345
+
346
+ return 0 ;
347
+ }
227
348
228
349
#if OCAC_USE_RESPONSE_HANDLER == 1
229
350
__weak void ocac_core_response_handler (Ocp1ResponseRef * response );
0 commit comments