socan 1.2.1
Linux SocketCAN higher level library
Loading...
Searching...
No Matches
sci.c
1/*==========================================================
2 MultiCAN - CAN Bus support for EPICS
3 module SCI
4 ==========================================================
5
6Copyright 2025 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
7<https://www.helmholtz-berlin.de>
8
9Author: Goetz Pfeiffer <Goetz.Pfeiffer@helmholtz-berlin.de>
10
11This file is part of SCI, the simple CAN interface which is part of MultiCAN.
12
13MultiCAN is free software: you can redistribute it and/or modify
14it under the terms of the GNU General Public License as published by
15the Free Software Foundation, either version 3 of the License, or
16(at your option) any later version.
17
18MultiCAN is distributed in the hope that it will be useful,
19but WITHOUT ANY WARRANTY; without even the implied warranty of
20MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21GNU General Public License for more details.
22
23You should have received a copy of the GNU General Public License
24along with MultiCAN. If not, see <https://www.gnu.org/licenses/>.
25*/
26
27/*
28summary:
29 This is the Simple CAN Interface, a library that provides types and
30 functions to work with a CAN bus interface in a hardware independent way.
31*/
32
33/* ----------------------------------------------
34 * includes
35 * ---------------------------------------------- */
36
37#include <stdlib.h>
38#include <stdbool.h>
39#include <stdio.h>
40#include <string.h>
41
42/* threads, mutexes: */
43#include <pthread.h>
44
45/* nanosleep: */
46#include <time.h>
47
48#include <socan.h>
49
50#include <sci.h>
51
52/* ----------------------------------------------
53 * macros
54 * ---------------------------------------------- */
55
56#define SCI_ERR(errcode) (SCI_ERROR | ((errcode)<<16))
57
58#define SCI_ERR_RC(rc,errcode) (SCI_ERROR | ((errcode)<<16) | (rc))
59
60/* ----------------------------------------------
61 * types
62 * ---------------------------------------------- */
63
65 {
66 socan_hdl hdl;
67 sci_Errcode errcode;
68 };
69
70typedef struct
71 { int real_port;
72 sci_Plug_Func h2l; /* sci to CAN plug-function */
73 sci_Plug_Func l2h; /* CAN to sci plug-function */
74 sci_Plug_Lencalc lcalc; /* calc CAN-length from user-length */
76
78 {
79 void *userp;
80 unsigned char port; /* When plugin is defined, the *logical* port, not
81 the real port */
82 unsigned char realport; /* When plugin is defined, the *real* port */
83 unsigned short cob;
84 unsigned char length;
85 unsigned char reallength;
86 struct sci_object_s *child;
87 };
88
89/* ----------------------------------------------
90 * variables
91 * ---------------------------------------------- */
92
93static pthread_mutex_t global_semaphore;
94
95static sci_plug_struc sci_plug_in[SCI_MAX_PLUGPORTS];
96
97/* ----------------------------------------------
98 * functions
99 * ---------------------------------------------- */
100
101/* ----------------------------------------------
102 * time module
103 * ---------------------------------------------- */
104
105static void mldelay(long milliseconds)
106/* millisecond-delay, works without "dirty tricks"
107 warning: the actual resolution may be smaller, e.g 1/60th of a second*/
108 { struct timespec rq,rt;
109
110 /* POSIX-conform wait */
111 if (milliseconds >= 1000L)
112 { rq.tv_sec = milliseconds / 1000L;
113 rq.tv_nsec= (milliseconds-1000L*rq.tv_sec) * 1000000L;
114 }
115 else
116 { rq.tv_sec = 0;
117 rq.tv_nsec= milliseconds * 1000000L;
118 };
119 nanosleep( &rq, &rt);
120 }
121
122/* ----------------------------------------------
123 * init
124 * ---------------------------------------------- */
125
126static bool mutex_init(pthread_mutex_t *mutex)
127 /* initialize mutex with PTHREAD_PRIO_INHERIT */
128 {
129 int rc;
130
131 pthread_mutexattr_t mutexattr;
132
133 rc= pthread_mutexattr_init(&mutexattr);
134 if (rc!=0)
135 {
136 return false;
137 }
138 rc= pthread_mutexattr_setprotocol(&mutexattr, PTHREAD_PRIO_INHERIT);
139 if (rc!=0)
140 {
141 return false;
142 }
143 rc= pthread_mutex_init(mutex, &mutexattr);
144 if (rc!=0)
145 {
146 return false;
147 }
148 return true;
149 }
150
151_Atomic static int _lock= 0;
152
153static int initialized= 0;
154/* 0: not initialized
155 * 1: initialized
156 * -1: error */
157
158static bool init_sci_lib(void)
159 {
160 int i;
161 sci_plug_struc *ps;
162
163 if (initialized==1)
164 return true;
165 if (initialized<0)
166 return false;
167
168 /* reading and writing to _lock is atomic: */
169 if (_lock++)
170 {
171 /* some other thread is initializing, check every 10ms if it is
172 * finished */
173 while (initialized==0)
174 mldelay(10);
175 if (initialized==1)
176 return true;
177 if (initialized<0)
178 return false;
179 }
180
181 if (!mutex_init(&global_semaphore))
182 {
183 initialized= -1;
184 return false;
185 }
186 for(i=0; i<SCI_MAX_PLUGPORTS; i++)
187 {
188 ps= &(sci_plug_in[i]);
189 ps->real_port= -1;
190 ps->h2l= NULL;
191 ps->l2h= NULL;
192 ps->lcalc= NULL;
193 }
194 initialized= 1;
195 return true;
196 }
197
198/* ----------------------------------------------
199 * socan_rc mapping
200 * ---------------------------------------------- */
201
202static bool map_socan_rc(socan_rc rc,
203 sci_Return *sci_rc,
204 sci_Errcode *sci_err)
205 /* returns true when there is no error, otherwise false */
206 {
207 *sci_rc= SCI_NOTHING;
208 *sci_err= SCI_NO_ERR;
209 switch(rc)
210 {
211 case SOCAN_OK:
212 return true;
213 case SOCAN_TIMEOUT:
214 *sci_rc= SCI_TMOUT;
215 return true;
216 case SOCAN_OLD:
217 *sci_rc= SCI_OLD_DATA;
218 return true;
219 case SOCAN_LOST:
220 *sci_rc= SCI_LOST;
221 return true;
222 case SOCAN_WAIT:
223 *sci_rc= SCI_WAIT;
224 return true;
225 case SOCAN_EXISTS:
226 *sci_rc= SCI_EXISTS;
227 return true;
228 case SOCAN_LENGTH_ERR:
229 *sci_rc= SCI_ERROR;
230 *sci_err= SCI_LENGTH_ERR;
231 return false;
232 case SOCAN_PORT_ERR:
233 *sci_rc= SCI_ERROR;
234 *sci_err= SCI_PORT_ERR;
235 return false;
236 case SOCAN_COB_ERR:
237 *sci_rc= SCI_ERROR;
238 *sci_err= SCI_ID_ERR;
239 return false;
240 case SOCAN_NOT_RO_ERR:
241 case SOCAN_NOT_WO_ERR:
242 case SOCAN_TYPE_ERR:
243 *sci_rc= SCI_ERROR;
244 *sci_err= SCI_MODE_ERR;
245 return false;
247 *sci_rc= SCI_ERROR;
248 *sci_err= SCI_OBJ_UNDEF_ERR;
249 return false;
251 *sci_rc= SCI_ERROR;
252 *sci_err= SCI_ACCESS_ERR;
253 return false;
254 case SOCAN_EXISTS_ERR:
255 *sci_rc= SCI_ERROR;
256 *sci_err= SCI_ACCESS_ERR;
257 return false;
258 case SOCAN_ERROR:
259 *sci_rc= SCI_ERROR;
260 *sci_err= SCI_ERR_GENERAL;
261 return false;
262 default:
263 /* shouldn't happen */
264 fprintf(stderr, "%s line %d: internal error\n", __FILE__, __LINE__);
265 *sci_rc= SCI_ERROR;
266 *sci_err= SCI_ERR_GENERAL;
267 return false;
268 }
269 }
270
271/* ----------------------------------------------
272 * socan_obj_type mapping
273 * ---------------------------------------------- */
274
275static bool map_socan_type(socan_obj_type stype, sci_Object_Type *type)
276 {
277 switch(stype)
278 {
279 case SOCAN_READ:
280 *type= SCI_READ;
281 return true;
282 case SOCAN_WRITE:
283 *type= SCI_WRITE;
284 return true;
285 case SOCAN_READ_RTR:
286 *type= SCI_REMOTE_READ;
287 return true;
288 case SOCAN_WRITE_RTR:
289 *type= SCI_REMOTE_WRITE;
290 return true;
291 default:
292 fprintf(stderr, "%s line %d: internal error\n", __FILE__, __LINE__);
293 *type= SCI_READ;
294 return false;
295 }
296 }
297
298static bool map_sci_type(sci_Object_Type type, socan_obj_type *stype)
299 {
300 switch(type)
301 {
302 case SCI_READ:
303 *stype= SOCAN_READ;
304 return true;
305 case SCI_WRITE:
306 *stype= SOCAN_WRITE;
307 return true;
308 case SCI_REMOTE_READ:
309 *stype= SOCAN_READ_RTR;
310 return true;
311 case SCI_REMOTE_WRITE:
312 *stype= SOCAN_WRITE_RTR;
313 return true;
314 default:
315 fprintf(stderr, "%s line %d: internal error\n", __FILE__, __LINE__);
316 *stype= SOCAN_READ;
317 return false;
318 }
319 }
320
321/* ----------------------------------------------
322 * printing the status and error code
323 * ---------------------------------------------- */
324
325#define CCODE(x) if (val==x) return(#x)
326
327char *sci_str_status(sci_Return val)
328 {
329 CCODE(SCI_NOTHING);
330 CCODE(SCI_OLD_DATA);
331 CCODE(SCI_LOST);
332 CCODE(SCI_TMOUT);
333 CCODE(SCI_RESETTED);
334 CCODE(SCI_INCONSISTENT);
335 CCODE(SCI_EXISTS);
336 CCODE(SCI_WAIT);
337 CCODE(SCI_ERROR);
338 fprintf(stderr, "%s line %d: unknown status code\n", __FILE__, __LINE__);
339 return("UNKNOWN STATUS!");
340 }
341
342void sci_print_status(sci_Return flag)
343 {
344 puts(sci_str_status(flag));
345 }
346
347char *sci_str_err(sci_Errcode val)
348 {
349 CCODE(SCI_NO_ERR);
350 CCODE(SCI_PORT_ERR);
351 CCODE(SCI_ID_ERR);
352 CCODE(SCI_TYPE_ERR);
353 CCODE(SCI_BITRATE_ERR);
354 CCODE(SCI_SET_CALLB_ERR);
355 CCODE(SCI_MODE_ERR);
356 CCODE(SCI_LENGTH_ERR);
357 CCODE(SCI_ACCESS_ERR);
358 CCODE(SCI_TIMEOUT_ERR);
359 CCODE(SCI_TIMEOUT_VAL_ERR);
360 CCODE(SCI_OFF_BUS_ERR);
361 CCODE(SCI_BUS_ERR);
362 CCODE(SCI_AUTHORIZE_ERR);
363 CCODE(SCI_DVR_OPEN_ERR);
364 CCODE(SCI_DVR_ACCESS_ERR);
365 CCODE(SCI_HW_INIT_ERR);
366 CCODE(SCI_RESET_ERR);
367 CCODE(SCI_CHIP_CONF_ERR);
368 CCODE(SCI_ENV_ERR);
369 CCODE(SCI_PLUGPORT_ERR);
370 CCODE(SCI_PLUG_DEF_ERR);
371 CCODE(SCI_OBJ_UNDEF_ERR);
372 CCODE(SCI_ERR_GENERAL);
373 fprintf(stderr, "%s line %d: unknown error code\n", __FILE__, __LINE__);
374 return("UNKNOWN ERROR CODE!");
375 }
376
377void sci_print_err(sci_Errcode err)
378 {
379 puts(sci_str_err(err));
380 }
381
382/* ----------------------------------------------
383 * sci plugin
384 * ---------------------------------------------- */
385
386static bool plug_get(unsigned short port, sci_plug_struc **ps)
387 /* returns:
388 * false: an error occured
389 * true : no error occured
390 * Note: *ps is NULL if there is no plugin
391 */
392 {
393 unsigned short plug;
394 *ps=NULL;
395
396 if (port < SCI_PLUGPORT_START)
397 return true; /* no plugin */
398 plug= port - SCI_PLUGPORT_START;
399 if (plug>=SCI_MAX_PLUGPORTS)
400 {
401 fprintf(stderr, "%s line %d: internal error\n", __FILE__, __LINE__);
402 return false;
403 }
404 *ps= &(sci_plug_in[plug]);
405 if ((*ps)->real_port==-1)
406 {
407 fprintf(stderr, "%s line %d: internal error\n", __FILE__, __LINE__);
408 return false;
409 }
410 return true;
411 }
412
413static bool plug_real_port(unsigned short port, unsigned short *realport)
414 /* return the *real* can port
415 * returns:
416 * false: an error occured
417 * true : no error occured
418 */
419 {
420 sci_plug_struc *ps;
421
422 *realport= port;
423 if (!plug_get(port, &ps))
424 return false;
425 if (ps==NULL)
426 return true;
427 *realport= ps->real_port;
428 return true;
429 }
430
431sci_Return sci_def_plug_in(unsigned short plug_port,
432 unsigned short real_port,
434 sci_Plug_Lencalc lcalc,
435 sci_Errcode *err)
436 { sci_plug_struc *ps;
437
438 if (!init_sci_lib()) /* actually initialization is only done once */
439 {
440 if (err!=NULL)
441 *err= SCI_ERR_GENERAL;
442 return SCI_ERR(SCI_ERR_GENERAL);
443 };
444 if ((plug_port<SCI_PLUGPORT_START) ||
446 { if (err!=NULL)
447 *err= SCI_PLUGPORT_ERR;
448 return SCI_ERR(SCI_PLUGPORT_ERR);
449 };
450 pthread_mutex_lock(&global_semaphore);
451 ps= &(sci_plug_in[plug_port-SCI_PLUGPORT_START]);
452 if (ps->real_port!=-1) /* that plug-port was already defined */
453 { if (err!=NULL)
454 *err= SCI_PLUG_DEF_ERR;
455 pthread_mutex_unlock(&global_semaphore);
456 return SCI_ERR(SCI_PLUG_DEF_ERR);
457 };
458 ps->real_port= real_port;
459 ps->h2l= h2l;
460 ps->l2h= l2h;
461 ps->lcalc= lcalc;
462 pthread_mutex_unlock(&global_semaphore);
463 return SCI_NOTHING;
464 }
465
466/* ----------------------------------------------
467 * open/close
468 * ---------------------------------------------- */
469
470sci_Return sci_open(sci_Struc **s_struc, const char *app_name,
471 sci_Errcode *err)
472 /* note: app_name is *ignored* in this implementation. */
473 {
474 socan_hdl hdl;
475 struct sci_struc_s *scistruc_p;
476
477 if (s_struc!=NULL)
478 *s_struc= NULL;
479 if (err!=NULL)
480 *err= SCI_NO_ERR;
481 if (!init_sci_lib()) /* actually initialization is only done once */
482 {
483 if (err!=NULL)
484 *err= SCI_ERR_GENERAL;
485 return(SCI_ERR(SCI_ERR_GENERAL));
486 };
487 pthread_mutex_lock(&global_semaphore);
488 hdl= socan_open();
489 if (hdl==NULL)
490 {
491 pthread_mutex_unlock(&global_semaphore);
492 if (err!=NULL)
493 *err= SCI_DVR_OPEN_ERR;
494 return SCI_ERR(SCI_DVR_OPEN_ERR);
495 }
496
497 scistruc_p= calloc(1, sizeof(struct sci_struc_s));
498 scistruc_p->hdl= hdl;
499 scistruc_p->errcode= SCI_NO_ERR;
500 *s_struc= scistruc_p;
501 pthread_mutex_unlock(&global_semaphore);
502 return SCI_NOTHING;
503 }
504
505sci_Return sci_close(sci_Struc **s_struc)
506 {
507 sci_Return rc= SCI_NOTHING;
508
509 if (!socan_close( (*((struct sci_struc_s**)s_struc))->hdl))
510 rc= SCI_ERROR;
511 pthread_mutex_lock(&global_semaphore);
512 free(*s_struc);
513 *s_struc= NULL;
514 pthread_mutex_unlock(&global_semaphore);
515 return rc;
516 }
517
518/* ----------------------------------------------
519 * sci_init : not implemented
520 * ---------------------------------------------- */
521
522#if 0
523sci_Return sci_init(sci_Struc *s_struc,
524 unsigned short port, sci_Bitrate bitrate)
525#endif
526
527/* ----------------------------------------------
528 * sci_reset : not implemented
529 * ---------------------------------------------- */
530
531#if 0
532sci_Return sci_reset(sci_Struc *s_struc, unsigned short port)
533#endif
534
535/* ----------------------------------------------
536 * get bitrate
537 * ---------------------------------------------- */
538
539sci_Return sci_get_bitrate(sci_Struc *s_struc,
540 unsigned short port, sci_Bitrate *bitrate)
541 {
542 socan_rc rc;
543 sci_Return sci_rc;
544 sci_Errcode sci_err;
545 unsigned int br;
546
547 if (!plug_real_port(port, &port))
548 {
549 s_struc->errcode= SCI_PLUGPORT_ERR;
550 return SCI_ERR(s_struc->errcode);
551 };
552
553 rc= socan_port_bitrate((unsigned char)port, &br);
554 if (!map_socan_rc(rc, &sci_rc, &sci_err))
555 {
556 s_struc->errcode= sci_err;
557 return SCI_ERR_RC(sci_rc, sci_err);
558 }
559
560 switch (br)
561 { case 1000000:
562 *bitrate= SCI_1000KB;
563 break;
564 case 500000:
565 *bitrate= SCI_500KB;
566 break;
567 case 250000:
568 *bitrate= SCI_250KB;
569 break;
570 case 125000:
571 *bitrate= SCI_125KB;
572 break;
573 case 100000:
574 *bitrate= SCI_100KB;
575 break;
576 case 66000:
577 *bitrate= SCI_66KB;
578 break;
579 case 66600:
580 *bitrate= SCI_66KB;
581 break;
582 case 66666:
583 *bitrate= SCI_66KB;
584 break;
585 case 50000:
586 *bitrate= SCI_50KB;
587 break;
588 case 20000:
589 *bitrate= SCI_20KB;
590 break;
591 default:
592 s_struc->errcode= SCI_ERR_GENERAL;
593 return SCI_ERR(s_struc->errcode);
594 };
595 return SCI_NOTHING;
596 }
597
598/* ----------------------------------------------
599 * get errcode
600 * ---------------------------------------------- */
601
602sci_Return sci_get_errcode(sci_Struc *s_struc, sci_Errcode *errcode)
603 /* similar to the traditional "errno" */
604 {
605 *errcode= s_struc->errcode;
606 return SCI_NOTHING;
607 }
608
609/* ----------------------------------------------
610 * get object
611 * ---------------------------------------------- */
612
613sci_Return sci_get_object(sci_Struc *s_struc, sci_Object **object,
614 unsigned short port, int id)
615 /* return sci_Object for a given port and id,
616 * returns SCI_OBJ_UNDEF_ERR if the sci_Object is not defined.
617 */
618 {
619 socan_rc rc;
620 sci_Return sci_rc;
621 sci_Errcode sci_err;
622 void *ptr;
623
624 if (!plug_real_port(port, &port))
625 {
626 s_struc->errcode= SCI_PLUGPORT_ERR;
627 return SCI_ERR(s_struc->errcode);
628 };
629
630 rc= socan_user_area(port, id, &ptr);
631 if (!map_socan_rc(rc, &sci_rc, &sci_err))
632 {
633 s_struc->errcode= sci_err;
634 return SCI_ERR_RC(sci_rc, sci_err);
635 }
636 if (ptr==NULL)
637 {
638 fprintf(stderr, "%s line %d: internal error\n", __FILE__, __LINE__);
639 return SCI_ERR(SCI_ERR_GENERAL);
640 }
641 *object= (sci_Object *)ptr;
642 return SCI_NOTHING;
643 }
644
645/* ----------------------------------------------
646 * get user part
647 * ---------------------------------------------- */
648
649void *sci_get_user(sci_Object *object)
650 {
651 return (object->userp);
652 }
653
654/* ----------------------------------------------
655 * get object properties
656 * ---------------------------------------------- */
657
658sci_Return sci_get_info(sci_Struc *s_struc, sci_Object *object,
659 unsigned short *port, int *id, int *length,
660 int *timeout, sci_Object_Type *type)
661 {
662 unsigned char l;
663 unsigned int tmo;
665 sci_Return sci_rc;
666 sci_Errcode sci_err;
667
668 socan_rc rc= socan_obj_info(s_struc->hdl, object->realport,
669 object->cob, &l, &tmo, &tp);
670 if (!map_socan_rc(rc, &sci_rc, &sci_err))
671 {
672 s_struc->errcode= sci_err;
673 return SCI_ERR_RC(sci_rc, sci_err);
674 }
675 *port= object->port;
676 *id= object->cob;
677 *length= object->length;
678 *timeout= tmo;
679 if (map_socan_type(tp, type))
680 {
681 s_struc->errcode= SCI_ERR_GENERAL;
682 return SCI_ERR_RC(rc, s_struc->errcode);
683 }
684 return sci_rc;
685 }
686
687/* ----------------------------------------------
688 * get object timestamp
689 * ---------------------------------------------- */
690
691sci_Return sci_get_timestamp(sci_Struc *s_struc, sci_Object *object,
692 unsigned long long *pstamp, int *pvalid,
693 unsigned char *mode, unsigned char *irq_cnt)
694 {
695 socan_rc rc;
696 sci_Return sci_rc;
697 sci_Errcode sci_err;
698 unsigned long ts;
699
700 rc= socan_obj_ts(object->realport, object->cob, &ts);
701 if (!map_socan_rc(rc, &sci_rc, &sci_err))
702 {
703 s_struc->errcode= sci_err;
704 return SCI_ERR_RC(sci_rc, sci_err);
705 }
706 *pstamp= ts;
707 *pvalid= 1;
708 *mode= 0; /* not implemented in socan */
709 *irq_cnt=0; /* not exported by socan */
710 return SCI_NOTHING;
711 }
712
713/* ----------------------------------------------
714 * dump object
715 * ---------------------------------------------- */
716
717sci_Return sci_obj_dump_buf(char *buf,
718 sci_Struc *s_struc, sci_Object *object)
719 {
720 sci_Return sci_rc;
721 unsigned short port;
722 int id;
723 int length;
724 int timeout;
725 sci_Object_Type type;
726 const char *str= "UNKNOWN TYPE!";
727
728 sci_rc= sci_get_info(s_struc, object, &port, &id, &length,
729 &timeout, &type);
730 if (sci_rc & SCI_ERROR)
731 { sprintf(buf, "sci_obj_dump_buf: sci_get_info failed\n");
732 return sci_rc;
733 };
734 switch(type)
735 { case SCI_READ: str= "SCI_READ"; break;
736 case SCI_WRITE: str= "SCI_WRITE"; break;
737 case SCI_REMOTE_READ: str= "SCI_REMOTE_READ"; break;
738 case SCI_REMOTE_WRITE: str="SCI_REMOTE_WRITE"; break;
739 };
740 sprintf(buf,"id:%d length:%d tmout:%d port:%d type:%s\n",
741 id,length,timeout,port,str);
742
743 return sci_rc;
744 }
745
746#if 0
747sci_Return sci_obj_dump(sci_Struc *s_struc, sci_Object *object)
748#endif
749
750/* ----------------------------------------------
751 * init object
752 * ---------------------------------------------- */
753
754sci_Return sci_init_object(sci_Struc *s_struc, sci_Object **object,
755 unsigned short port, int id, int length,
756 int timeout, sci_Object_Type type, void *userp)
757 {
758 /* duplicates object if it already exists */
759 socan_rc rc;
760 sci_Return sci_rc;
761 sci_Errcode sci_err;
762 sci_plug_struc *ps;
763 unsigned short realport= port;
764 unsigned char reallength= (unsigned char)length;
765 struct sci_object_s *obj;
766 sci_Object *root, *parent, *new;
767 socan_obj_type stype;
768
769 if (!plug_get(port, &ps))
770 {
771 s_struc->errcode= SCI_PLUGPORT_ERR;
772 return SCI_ERR(s_struc->errcode);
773 }
774 if (ps!=NULL)
775 {
776 int l;
777 /* plugin defined */
778 realport= ps->real_port;
779 if (!(ps->lcalc)(length, &l))
780 {
781 s_struc->errcode= SCI_LENGTH_ERR;
782 return SCI_ERR(s_struc->errcode);
783 }
784 reallength= (unsigned char)l;
785 }
786 if (!map_sci_type(type, &stype))
787 {
788 s_struc->errcode= SCI_TYPE_ERR;
789 return SCI_ERR(s_struc->errcode);
790 }
791
792 rc= socan_add_obj(s_struc->hdl, realport,
793 id, reallength,
794 (unsigned int)timeout, stype);
795 if (!map_socan_rc(rc, &sci_rc, &sci_err))
796 {
797 s_struc->errcode= sci_err;
798 return SCI_ERR_RC(sci_rc, sci_err);
799 }
800 if (rc==SOCAN_EXISTS)
801 { /* CAN object exists, must duplicate */
802 pthread_mutex_lock(&global_semaphore);
803 rc= socan_user_area(realport, id, (void**)(&root));
804 if (!map_socan_rc(rc, &sci_rc, &sci_err))
805 {
806 s_struc->errcode= sci_err;
807 pthread_mutex_unlock(&global_semaphore);
808 return SCI_ERR_RC(sci_rc, sci_err);
809 }
810 if (root==NULL)
811 {
812 fprintf(stderr, "%s line %d: internal error\n", __FILE__, __LINE__);
813 s_struc->errcode= SCI_ERR_GENERAL;
814 pthread_mutex_unlock(&global_semaphore);
815 return SCI_ERR(s_struc->errcode);
816 }
817 for(parent= root; parent->child!=NULL; parent= parent->child);
818 new= calloc(1, sizeof(struct sci_object_s));
819 new->userp= userp;
820 new->port= parent->port;
821 new->realport= parent->realport;
822 new->cob= parent->cob;
823 new->length= parent->length;
824 new->reallength= parent->reallength;
825 *object= new;
826 pthread_mutex_unlock(&global_semaphore);
827 return SCI_NOTHING;
828 }
829
830 rc= socan_new_user_area(realport, id, sizeof(struct sci_object_s),
831 (void**)(&obj));
832 if (!map_socan_rc(rc, &sci_rc, &sci_err))
833 {
834 s_struc->errcode= sci_err;
835 return SCI_ERR_RC(sci_rc, sci_err);
836 }
837 obj->userp= userp;
838 obj->port= port;
839 obj->realport= realport;
840 obj->cob= id;
841 obj->length= (unsigned char)length;
842 obj->reallength= reallength;
843 obj->child= NULL;
844 *object= obj;
845 return SCI_NOTHING;
846 }
847
848/* ----------------------------------------------
849 * dup object
850 * ---------------------------------------------- */
851
852#if 0
853sci_Return sci_dup_object(sci_Struc *s_struc, sci_Object **dup_object,
854 sci_Object *object, void *userp)
855#endif
856
857/* ----------------------------------------------
858 * delete object
859 * ---------------------------------------------- */
860
861sci_Return sci_delete_object(sci_Struc *s_struc, sci_Object **object)
862 {
863 socan_rc rc;
864 sci_Return sci_rc;
865 sci_Errcode sci_err;
866 sci_Object *root, *parent;
867
868 rc= socan_user_area((*object)->realport, (*object)->cob, (void**)(&root));
869 if (!map_socan_rc(rc, &sci_rc, &sci_err))
870 {
871 s_struc->errcode= sci_err;
872 return SCI_ERR_RC(sci_rc, sci_err);
873 }
874 if (root==NULL)
875 {
876 s_struc->errcode= SCI_ERR_GENERAL;
877 return SCI_ERR(s_struc->errcode);
878 }
879 pthread_mutex_lock(&global_semaphore);
880 if (root==(*object))
881 {
882 if ((*object)->child != NULL)
883 {
884 rc= socan_set_user_area((*object)->realport, (*object)->cob,
885 (*object)->child);
886 if (!map_socan_rc(rc, &sci_rc, &sci_err))
887 {
888 fprintf(stderr, "%s line %d: internal error\n",
889 __FILE__, __LINE__);
890 s_struc->errcode= sci_err;
891 pthread_mutex_unlock(&global_semaphore);
892 return SCI_ERR_RC(sci_rc, sci_err);
893 }
894 free(*object);
895 *object= NULL;
896 pthread_mutex_unlock(&global_semaphore);
897 return SCI_NOTHING;
898 }
899 /* continue deleting object...*/
900 }
901 else
902 {
903 for(parent= root;
904 (parent->child!=(*object)) && (parent->child!=NULL);
905 parent= parent->child);
906 if (parent->child != (*object))
907 { /* not found */
908 fprintf(stderr, "%s line %d: internal error\n", __FILE__, __LINE__);
909 s_struc->errcode= SCI_ERR_GENERAL;
910 pthread_mutex_unlock(&global_semaphore);
911 return SCI_ERR(s_struc->errcode);
912 }
913 parent->child= (*object)->child;
914 free(*object);
915 *object= NULL;
916 pthread_mutex_unlock(&global_semaphore);
917 return SCI_NOTHING;
918 }
919
920 rc= socan_del_obj((*object)->realport, (*object)->cob);
921 if (!map_socan_rc(rc, &sci_rc, &sci_err))
922 {
923 s_struc->errcode= sci_err;
924 pthread_mutex_unlock(&global_semaphore);
925 return SCI_ERR_RC(sci_rc, sci_err);
926 }
927 *object= NULL;
928 pthread_mutex_unlock(&global_semaphore);
929 return sci_rc;
930 }
931
932
933/* ----------------------------------------------
934 * link object
935 * ---------------------------------------------- */
936
937#if 0
938sci_Return sci_link_object(sci_Struc *s_struc,
939 unsigned short read_port , int read_id,
940 unsigned short write_port, int write_id,
941 int length, int timeout,
942 void *read_user, void *write_user)
943#endif
944
945/* ----------------------------------------------
946 * set inhibit
947 * ---------------------------------------------- */
948
949sci_Return sci_set_inhibit(sci_Struc *s_struc, sci_Object *object,
950 unsigned long inhibit_time)
951 {
952 socan_rc rc;
953 sci_Return sci_rc;
954 sci_Errcode sci_err;
955
956 rc= socan_set_inhibit(object->realport, object->cob, inhibit_time);
957 if (!map_socan_rc(rc, &sci_rc, &sci_err))
958 {
959 s_struc->errcode= sci_err;
960 return SCI_ERR_RC(sci_rc, sci_err);
961 }
962 return sci_rc;
963 }
964
965/* ----------------------------------------------
966 * set callback
967 * ---------------------------------------------- */
968
969sci_Return sci_set_callback(sci_Struc *s_struc, sci_Object *object,
970 void *f)
971/* f must always be NULL */
972 {
973 socan_rc rc;
974 sci_Return sci_rc;
975 sci_Errcode sci_err;
976
977 rc= socan_use_queue(object->realport, object->cob);
978 if (!map_socan_rc(rc, &sci_rc, &sci_err))
979 {
980 s_struc->errcode= sci_err;
981 return SCI_ERR_RC(sci_rc, sci_err);
982 }
983 return sci_rc;
984 }
985
986
987/* ----------------------------------------------
988 * write object
989 * ---------------------------------------------- */
990
991static sci_Return can_write(sci_Struc *s_struc, sci_Object *object,
992 char *data, unsigned long *rest_time)
993 {
994 socan_rc rc;
995 sci_Return sci_rc;
996 sci_Errcode sci_err;
997 sci_plug_struc *ps;
998 char buf[SOCAN_FRAME_LENGTH];
999
1000 if (!plug_get(object->port, &ps))
1001 {
1002 s_struc->errcode= SCI_PLUGPORT_ERR;
1003 return SCI_ERR(s_struc->errcode);
1004 }
1005 if (ps!=NULL)
1006 {
1007 /* plugin defined */
1008 /* convert data: */
1009 (ps->h2l)(object->reallength, buf, object->length, data);
1010 data= buf;
1011 }
1012
1013 if (rest_time==NULL)
1014 rc= socan_writelater(s_struc->hdl, object->realport, object->cob, data);
1015 else
1016 rc= socan_write_inhibit(s_struc->hdl, object->realport, object->cob,
1017 data, rest_time);
1018
1019 if (!map_socan_rc(rc, &sci_rc, &sci_err))
1020 {
1021 s_struc->errcode= sci_err;
1022 return SCI_ERR_RC(sci_rc, sci_err);
1023 }
1024 return sci_rc;
1025 }
1026
1027sci_Return sci_write(sci_Struc *s_struc, sci_Object *object,
1028 char *data)
1029 {
1030 return can_write(s_struc, object, data, NULL);
1031 }
1032
1033sci_Return sci_write_inhibit(sci_Struc *s_struc, sci_Object *object,
1034 char *data, unsigned long *rest_time)
1035
1036 {
1037 return can_write(s_struc, object, data, rest_time);
1038 }
1039
1040/* ----------------------------------------------
1041 * read
1042 * ---------------------------------------------- */
1043
1044static sci_Return can_read(sci_Struc *s_struc, sci_Object *object,
1045 char *data, bool read_now)
1046 {
1047 socan_rc rc;
1048 sci_Return sci_rc;
1049 sci_Errcode sci_err;
1050 sci_plug_struc *ps;
1051 char buf[SOCAN_FRAME_LENGTH];
1052
1053 if (!plug_get(object->port, &ps))
1054 {
1055 s_struc->errcode= SCI_PLUGPORT_ERR;
1056 return SCI_ERR(s_struc->errcode);
1057 }
1058 if (read_now)
1059 rc= socan_readnow(s_struc->hdl, object->realport, object->cob, data);
1060 else
1061 rc= socan_read(s_struc->hdl, object->realport, object->cob, data);
1062
1063 if (!map_socan_rc(rc, &sci_rc, &sci_err))
1064 {
1065 s_struc->errcode= sci_err;
1066 return SCI_ERR_RC(sci_rc, sci_err);
1067 }
1068 if (ps!=NULL)
1069 {
1070 /* plugin defined */
1071 /* convert data: */
1072 (ps->l2h)(object->reallength, data, object->length, buf);
1073 memcpy(data, buf, object->length);
1074 }
1075 return sci_rc;
1076 }
1077
1078sci_Return sci_read_now(sci_Struc *s_struc, sci_Object *object,
1079 char *data)
1080 {
1081 return can_read(s_struc, object, data, true);
1082 }
1083
1084#if 0
1085sci_Return sci_read_new(sci_Struc *s_struc, sci_Object *object,
1086 char *data)
1087#endif
1088
1089sci_Return sci_read(sci_Struc *s_struc, sci_Object *object,
1090 char *data)
1091 {
1092 return can_read(s_struc, object, data, false);
1093 }
1094
1095/* ----------------------------------------------
1096 * queue read
1097 * ---------------------------------------------- */
1098
1099sci_Return sci_queue_read(sci_Struc *s_struc, sci_Object **object,
1100 char *data)
1101 {
1102 socan_rc rc;
1103 sci_Return sci_rc;
1104 sci_Errcode sci_err;
1105 unsigned short cob;
1106 unsigned char port;
1107 sci_plug_struc *ps;
1108 struct sci_object_s *obj;
1109
1110 *object= NULL;
1111 rc= socan_queue_read(s_struc->hdl, &port, &cob, data);
1112 if (!map_socan_rc(rc, &sci_rc, &sci_err))
1113 {
1114 s_struc->errcode= sci_err;
1115 return SCI_ERR_RC(sci_rc, sci_err);
1116 }
1117 rc= socan_user_area(port, cob, (void**)(&obj));
1118 if (!map_socan_rc(rc, &sci_rc, &sci_err))
1119 {
1120 s_struc->errcode= sci_err;
1121 return SCI_ERR_RC(sci_rc, sci_err);
1122 }
1123 if (obj==NULL)
1124 {
1125 fprintf(stderr, "%s line %d: internal error\n", __FILE__, __LINE__);
1126 return SCI_ERR(SCI_ERR_GENERAL);
1127 }
1128 if (!plug_get(obj->port, &ps))
1129 {
1130 s_struc->errcode= SCI_PLUGPORT_ERR;
1131 return SCI_ERR_RC(sci_rc, sci_err);
1132 }
1133 if (ps!=NULL)
1134 {
1135 /* plugin defined */
1136 /* convert data: */
1137 char buf[SOCAN_FRAME_LENGTH];
1138 (ps->l2h)(obj->reallength, data, obj->length, buf);
1139 memcpy(data, buf, obj->length);
1140 }
1141 *object= obj;
1142 return sci_rc;
1143 }
1144
c header file for the simple CAN interface (sci)
#define SCI_PLUGPORT_START
Definition sci.h:106
void(* sci_Plug_Func)(int l_len, char *l_data, int h_len, char *h_data)
Definition sci.h:399
@ SCI_EXISTS
Definition sci.h:275
@ SCI_NOTHING
Definition sci.h:268
@ SCI_WAIT
Definition sci.h:276
@ SCI_INCONSISTENT
Definition sci.h:274
@ SCI_OLD_DATA
Definition sci.h:269
@ SCI_ERROR
Definition sci.h:278
@ SCI_LOST
Definition sci.h:270
@ SCI_RESETTED
Definition sci.h:273
@ SCI_TMOUT
Definition sci.h:272
enum sci_Errcode_Constants sci_Errcode
#define SCI_MAX_PLUGPORTS
Definition sci.h:114
@ SCI_1000KB
Definition sci.h:293
@ SCI_125KB
Definition sci.h:296
@ SCI_100KB
Definition sci.h:297
@ SCI_50KB
Definition sci.h:299
@ SCI_250KB
Definition sci.h:295
@ SCI_66KB
Definition sci.h:298
@ SCI_20KB
Definition sci.h:300
@ SCI_500KB
Definition sci.h:294
sci_Object_Type
Definition sci.h:225
@ SCI_READ
Definition sci.h:225
@ SCI_REMOTE_READ
Definition sci.h:227
@ SCI_REMOTE_WRITE
Definition sci.h:228
@ SCI_WRITE
Definition sci.h:226
int(* sci_Plug_Lencalc)(int h_len, int *l_len)
Definition sci.h:407
enum sci_Bitrate_Constants sci_Bitrate
@ SCI_ID_ERR
Definition sci.h:313
@ SCI_AUTHORIZE_ERR
Definition sci.h:327
@ SCI_PORT_ERR
Definition sci.h:312
@ SCI_ERR_GENERAL
Definition sci.h:340
@ SCI_MODE_ERR
Definition sci.h:317
@ SCI_ACCESS_ERR
Definition sci.h:321
@ SCI_PLUGPORT_ERR
Definition sci.h:334
@ SCI_BITRATE_ERR
Definition sci.h:315
@ SCI_TYPE_ERR
Definition sci.h:314
@ SCI_NO_ERR
Definition sci.h:311
@ SCI_HW_INIT_ERR
Definition sci.h:330
@ SCI_TIMEOUT_ERR
Definition sci.h:323
@ SCI_CHIP_CONF_ERR
Definition sci.h:332
@ SCI_BUS_ERR
Definition sci.h:326
@ SCI_DVR_OPEN_ERR
Definition sci.h:328
@ SCI_ENV_ERR
Definition sci.h:333
@ SCI_LENGTH_ERR
Definition sci.h:319
@ SCI_TIMEOUT_VAL_ERR
Definition sci.h:324
@ SCI_PLUG_DEF_ERR
Definition sci.h:337
@ SCI_OBJ_UNDEF_ERR
Definition sci.h:339
@ SCI_DVR_ACCESS_ERR
Definition sci.h:329
@ SCI_RESET_ERR
Definition sci.h:331
@ SCI_SET_CALLB_ERR
Definition sci.h:316
@ SCI_OFF_BUS_ERR
Definition sci.h:325
socan_rc socan_user_area(unsigned char port, unsigned short cob, void **area)
Definition socan.c:1642
bool socan_close(socan_hdl h)
Definition socan.c:1196
socan_rc socan_write_inhibit(socan_hdl hdl, unsigned char port, unsigned short cob, const void *data, unsigned long *inhibit_time)
Definition socan.c:2072
socan_rc socan_set_user_area(unsigned char port, unsigned short cob, void *ptr)
Definition socan.c:1658
socan_rc socan_port_bitrate(unsigned char port, unsigned int *bitrate)
Definition socan.c:1089
socan_rc socan_del_obj(unsigned char port, unsigned short cob)
Definition socan.c:1502
socan_rc socan_read(socan_hdl hdl, unsigned char port, unsigned short cob, void *data)
Definition socan.c:1758
socan_rc socan_obj_ts(unsigned char port, unsigned short cob, unsigned long *ts)
Definition socan.c:1549
socan_rc socan_use_queue(unsigned char port, unsigned short cob)
Definition socan.c:1600
socan_rc socan_readnow(socan_hdl hdl, unsigned char port, unsigned short cob, void *data)
Definition socan.c:1698
socan_rc socan_set_inhibit(unsigned char port, unsigned short cob, unsigned long inhibit_time)
Definition socan.c:1580
socan_hdl socan_open(void)
Definition socan.c:1151
socan_rc socan_queue_read(socan_hdl hdl, unsigned char *port, unsigned short *cob, void *data)
Definition socan.c:1867
socan_rc socan_add_obj(socan_hdl hdl, unsigned char port, unsigned short cob, unsigned char length, unsigned int tmo_ms, socan_obj_type type)
Definition socan.c:1459
socan_rc socan_writelater(socan_hdl hdl, unsigned char port, unsigned short cob, const void *data)
Definition socan.c:2000
socan_rc socan_obj_info(socan_hdl hdl, unsigned char port, unsigned short cob, unsigned char *length, unsigned int *tmo_ms, socan_obj_type *type)
Definition socan.c:1523
socan_rc socan_new_user_area(unsigned char port, unsigned short cob, unsigned int size, void **area)
Definition socan.c:1621
c header file for socan object layer library.
socan_rc
Definition socan.h:176
@ SOCAN_NOT_OWNED_ERR
Definition socan.h:194
@ SOCAN_ERROR
Definition socan.h:198
@ SOCAN_LOST
Definition socan.h:181
@ SOCAN_LENGTH_ERR
Definition socan.h:186
@ SOCAN_EXISTS
Definition socan.h:185
@ SOCAN_TYPE_ERR
Definition socan.h:191
@ SOCAN_TIMEOUT
Definition socan.h:178
@ SOCAN_COB_ERR
Definition socan.h:188
@ SOCAN_EXISTS_ERR
Definition socan.h:196
@ SOCAN_OLD
Definition socan.h:179
@ SOCAN_NOT_WO_ERR
Definition socan.h:190
@ SOCAN_WAIT
Definition socan.h:183
@ SOCAN_OK
Definition socan.h:177
@ SOCAN_PORT_ERR
Definition socan.h:187
@ SOCAN_NOT_RO_ERR
Definition socan.h:189
@ SOCAN_NOT_EXISTS_ERR
Definition socan.h:192
socan_obj_type
Definition socan.h:162
@ SOCAN_WRITE
Definition socan.h:164
@ SOCAN_WRITE_RTR
Definition socan.h:166
@ SOCAN_READ
Definition socan.h:163
@ SOCAN_READ_RTR
Definition socan.h:165
#define SOCAN_FRAME_LENGTH
Definition socan.h:137