@@ -162,8 +162,7 @@ static int co_sdo_rx_upload_init_req (
162
162
if (job -> sdo .remain <= sizeof (job -> sdo .value ))
163
163
{
164
164
/* Object values up to 64 bits are fetched atomically */
165
- abort =
166
- co_od_get_value (net , obj , entry , job -> sdo .subindex , & job -> sdo .value );
165
+ abort = co_od_get_value (net , obj , entry , job -> sdo .subindex , & job -> sdo .value );
167
166
job -> sdo .data = (uint8_t * )& job -> sdo .value ;
168
167
}
169
168
else
@@ -269,6 +268,48 @@ static int co_sdo_rx_upload_seg_req (
269
268
return 0 ;
270
269
}
271
270
271
+ static bool co_is_datatype_atomic (co_dtype_t datatype )
272
+ {
273
+ switch (datatype )
274
+ {
275
+ case DTYPE_BOOLEAN :
276
+ case DTYPE_INTEGER8 :
277
+ case DTYPE_INTEGER16 :
278
+ case DTYPE_INTEGER32 :
279
+ case DTYPE_UNSIGNED8 :
280
+ case DTYPE_UNSIGNED16 :
281
+ case DTYPE_UNSIGNED32 :
282
+ case DTYPE_REAL32 :
283
+ case DTYPE_REAL64 :
284
+ case DTYPE_INTEGER64 :
285
+ case DTYPE_UNSIGNED64 :
286
+ return true;
287
+
288
+ case DTYPE_VISIBLE_STRING :
289
+ case DTYPE_OCTET_STRING :
290
+ case DTYPE_UNICODE_STRING :
291
+ case DTYPE_TIME_OF_DAY :
292
+ case DTYPE_TIME_DIFFERENCE :
293
+ case DTYPE_DOMAIN :
294
+ case DTYPE_INTEGER24 :
295
+ case DTYPE_INTEGER40 :
296
+ case DTYPE_INTEGER48 :
297
+ case DTYPE_INTEGER56 :
298
+ case DTYPE_UNSIGNED24 :
299
+ case DTYPE_UNSIGNED40 :
300
+ case DTYPE_UNSIGNED48 :
301
+ case DTYPE_UNSIGNED56 :
302
+ case DTYPE_PDO_COMM_PARAM :
303
+ case DTYPE_PDO_MAPPING :
304
+ case DTYPE_SDO_PARAM :
305
+ case DTYPE_IDENTITY :
306
+ return false;
307
+
308
+ default :
309
+ return false;
310
+ }
311
+ }
312
+
272
313
static int co_sdo_rx_download_init_req (
273
314
co_net_t * net ,
274
315
uint8_t node ,
@@ -327,40 +368,13 @@ static int co_sdo_rx_download_init_req (
327
368
return -1 ;
328
369
}
329
370
330
- job -> sdo .remain = CO_BYTELENGTH (entry -> bitlength );
331
- job -> sdo .toggle = 0 ;
332
-
333
- if (job -> sdo .remain <= sizeof (job -> sdo .value ))
334
- {
335
- /* Object values up to 64 bits are cached so that we can set
336
- them atomically when the transfer is complete */
337
- job -> sdo .data = (uint8_t * )& job -> sdo .value ;
338
- job -> sdo .cached = true;
339
- }
340
- else
341
- {
342
- /* Otherwise a pointer is used to access object */
343
- abort = co_od_get_ptr (net , obj , entry , job -> sdo .subindex , & job -> sdo .data );
344
- if (abort )
345
- {
346
- co_sdo_abort (
347
- net ,
348
- 0x580 + net -> node ,
349
- job -> sdo .index ,
350
- job -> sdo .subindex ,
351
- abort );
352
- return -1 ;
353
- }
354
- }
355
-
356
371
/* Check for expedited download */
357
372
if (type & CO_SDO_E )
358
373
{
359
374
size_t size = (type & CO_SDO_S ) ? 4 - CO_SDO_N (type ) : 4 ;
360
- uint32_t value ;
361
375
362
376
/* Validate size */
363
- if (size != job -> sdo . remain )
377
+ if (size > CO_BYTELENGTH ( entry -> bitlength ) )
364
378
{
365
379
co_sdo_abort (
366
380
net ,
@@ -371,11 +385,35 @@ static int co_sdo_rx_download_init_req (
371
385
return -1 ;
372
386
}
373
387
374
- /* Fetch value */
375
- value = co_fetch_uint32 (& data [4 ]);
388
+ if (co_is_datatype_atomic (entry -> datatype ))
389
+ {
390
+ uint32_t value ;
376
391
377
- /* Atomically set value */
378
- abort = co_od_set_value (net , obj , entry , job -> sdo .subindex , value );
392
+ /* Fetch value */
393
+ value = co_fetch_uint32 (& data [4 ]);
394
+
395
+ /* Atomically set value */
396
+ abort = co_od_set_value (net , obj , entry , job -> sdo .subindex , value );
397
+ }
398
+ else
399
+ {
400
+ /* Pointer is used to access object */
401
+ abort = co_od_get_ptr (net , obj , entry , job -> sdo .subindex , & job -> sdo .data );
402
+ if (abort )
403
+ {
404
+ co_sdo_abort (
405
+ net ,
406
+ 0x580 + net -> node ,
407
+ job -> sdo .index ,
408
+ job -> sdo .subindex ,
409
+ abort );
410
+ return -1 ;
411
+ }
412
+
413
+ memcpy (job -> sdo .data , & data [4 ], size );
414
+
415
+ co_od_notify (net , obj , entry , job -> sdo .subindex , OD_NOTIFY_SDO_RECEIVED , size );
416
+ }
379
417
380
418
/* Done */
381
419
job -> type = CO_JOB_NONE ;
@@ -391,6 +429,46 @@ static int co_sdo_rx_download_init_req (
391
429
return -1 ;
392
430
}
393
431
}
432
+ else
433
+ {
434
+ job -> sdo .total = co_fetch_uint32 (& data [4 ]);
435
+ job -> sdo .remain = job -> sdo .total ;
436
+
437
+ if (job -> sdo .remain > CO_BYTELENGTH (entry -> bitlength ))
438
+ {
439
+ co_sdo_abort (
440
+ net ,
441
+ 0x580 + net -> node ,
442
+ job -> sdo .index ,
443
+ job -> sdo .subindex ,
444
+ CO_SDO_ABORT_LENGTH );
445
+ return -1 ;
446
+ }
447
+ job -> sdo .toggle = 0 ;
448
+
449
+ if (co_is_datatype_atomic (entry -> datatype ))
450
+ {
451
+ /* Datatypes with atomic functions are cached in job->sdo.value
452
+ * so they can be set atomically when the transfer is complete */
453
+ job -> sdo .data = (uint8_t * )& job -> sdo .value ;
454
+ job -> sdo .cached = true;
455
+ }
456
+ else
457
+ {
458
+ /* Otherwise a pointer is used to access object */
459
+ abort = co_od_get_ptr (net , obj , entry , job -> sdo .subindex , & job -> sdo .data );
460
+ if (abort )
461
+ {
462
+ co_sdo_abort (
463
+ net ,
464
+ 0x580 + net -> node ,
465
+ job -> sdo .index ,
466
+ job -> sdo .subindex ,
467
+ abort );
468
+ return -1 ;
469
+ }
470
+ }
471
+ }
394
472
395
473
/* Dictionary has been written to and is now dirty */
396
474
net -> config_dirty = 1 ;
@@ -447,37 +525,36 @@ static int co_sdo_rx_download_seg_req (
447
525
/* Write complete */
448
526
job -> type = CO_JOB_NONE ;
449
527
450
- if (job -> sdo .cached )
528
+ /* Find requested object */
529
+ obj = co_obj_find (net , job -> sdo .index );
530
+ if (obj == NULL )
451
531
{
452
- /* Find requested object */
453
- obj = co_obj_find (net , job -> sdo .index );
454
- if (obj == NULL )
455
- {
456
- co_sdo_abort (
457
- net ,
458
- 0x580 + net -> node ,
459
- job -> sdo .index ,
460
- job -> sdo .subindex ,
461
- CO_SDO_ABORT_BAD_INDEX );
462
- return -1 ;
463
- }
532
+ co_sdo_abort (
533
+ net ,
534
+ 0x580 + net -> node ,
535
+ job -> sdo .index ,
536
+ job -> sdo .subindex ,
537
+ CO_SDO_ABORT_BAD_INDEX );
538
+ return -1 ;
539
+ }
464
540
465
- /* Find requested subindex */
466
- entry = co_entry_find (net , obj , job -> sdo .subindex );
467
- if (entry == NULL )
468
- {
469
- co_sdo_abort (
470
- net ,
471
- 0x580 + net -> node ,
472
- job -> sdo .index ,
473
- job -> sdo .subindex ,
474
- CO_SDO_ABORT_BAD_SUBINDEX );
475
- return -1 ;
476
- }
541
+ /* Find requested subindex */
542
+ entry = co_entry_find (net , obj , job -> sdo .subindex );
543
+ if (entry == NULL )
544
+ {
545
+ co_sdo_abort (
546
+ net ,
547
+ 0x580 + net -> node ,
548
+ job -> sdo .index ,
549
+ job -> sdo .subindex ,
550
+ CO_SDO_ABORT_BAD_SUBINDEX );
551
+ return -1 ;
552
+ }
477
553
554
+ if (job -> sdo .cached )
555
+ {
478
556
/* Atomically set value */
479
- abort =
480
- co_od_set_value (net , obj , entry , job -> sdo .subindex , job -> sdo .value );
557
+ abort = co_od_set_value (net , obj , entry , job -> sdo .subindex , job -> sdo .value );
481
558
if (abort )
482
559
{
483
560
co_sdo_abort (
@@ -489,6 +566,10 @@ static int co_sdo_rx_download_seg_req (
489
566
return -1 ;
490
567
}
491
568
}
569
+ else
570
+ {
571
+ co_od_notify (net , obj , entry , job -> sdo .subindex , OD_NOTIFY_SDO_RECEIVED , job -> sdo .total );
572
+ }
492
573
}
493
574
494
575
/* Segmented response */
0 commit comments