1 /*
2 EIBD client library
3 Copyright (C) 2005-2006 Martin K�gler <mkoegler@auto.tuwien.ac.at>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 In addition to the permissions in the GNU General Public License,
11 you may link the compiled version of this file into combinations
12 with other programs, and distribute those combinations without any
13 restriction coming from the use of this file. (The General Public
14 License restrictions do apply in other respects; for example, they
15 cover modification of the file, and distribution when not linked into
16 a combine executable.)
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 */
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <sys/socket.h>
31 #include <sys/un.h>
32 #include <netinet/in.h>
33 #include <netdb.h>
34 #include <errno.h>
35 #include <string.h>
36
37 #include "config.h"
38
39 #include "eibclient.h"
40 #include "eibtypes.h"
41
42 /** unsigned char */
43 typedef uint8_t uchar;
44
45 /** EIB Connection internal */
46 struct _EIBConnection
47 {
48 int (*complete) (EIBConnection *);
49 /** file descriptor */
50 int fd;
51 pth_event_t ev;
52 unsigned readlen;
53 /** buffer */
54 uchar *buf;
55 /** buffer size */
56 unsigned buflen;
57 /** used buffer */
58 unsigned size;
59 struct
60 {
61 int len;
62 uint8_t *buf;
63 int16_t *ptr1;
64 uint8_t *ptr2;
65 uint8_t *ptr3;
66 uint16_t *ptr4;
67 }
68 req;
69 };
70
71 /** extracts TYPE code of an eibd packet */
72 #define EIBTYPE(con) (((con)->buf[0]<<8)|((con)->buf[1]))
73 /** sets TYPE code for an eibd packet*/
74 #define EIBSETTYPE(buf,type) do{(buf)[0]=(type>>8)&0xff;(buf)[1]=(type)&0xff;}while(0)
75
76 /** set EIB address */
77 #define EIBSETADDR(buf,type) do{(buf)[0]=(type>>8)&0xff;(buf)[1]=(type)&0xff;}while(0)
78
79 /** resolve host name */
80 static int
GetHostIP(struct sockaddr_in * sock,const char * Name)81 GetHostIP (struct sockaddr_in *sock, const char *Name)
82 {
83 #ifdef HAVE_GETHOSTBYNAME_R
84 int len = 2000;
85 struct hostent host;
86 char *buf = (char *) malloc (len);
87 int res;
88 int err;
89 #endif
90
91 struct hostent *h;
92 if (!Name)
93 return 0;
94 memset (sock, 0, sizeof (*sock));
95 #ifdef HAVE_GETHOSTBYNAME_R
96
97 do
98 {
99 res = gethostbyname_r (Name, &host, buf, len, &h, &err);
100 if (res == ERANGE)
101 {
102 len += 2000;
103 buf = (char *) realloc (buf, len);
104 }
105 if (!buf)
106 return 0;
107 }
108 while (res == ERANGE);
109
110 if (res || !h)
111 {
112 free (buf);
113 return 0;
114 }
115 #else
116 h = gethostbyname (Name);
117 if (!h)
118 return 0;
119 #endif
120
121 sock->sin_family = h->h_addrtype;
122 sock->sin_addr.s_addr = (*((unsigned long *) h->h_addr_list[0]));
123 #ifdef HAVE_GETHOSTBYNAME_R
124
125 if (buf)
126 free (buf);
127 #endif
128
129 return 1;
130 }
131
132 int
EIBClose(EIBConnection * con)133 EIBClose (EIBConnection * con)
134 {
135 if (!con)
136 {
137 errno = EINVAL;
138 return -1;
139 }
140 close (con->fd);
141 if (con->buf)
142 free (con->buf);
143 free (con);
144 return 0;
145 }
146
EIBSetEvent(EIBConnection * con,pth_event_t ev)147 void EIBSetEvent (EIBConnection * con, pth_event_t ev)
148 {
149 con->ev = ev;
150 }
151
152 EIBConnection *
EIBSocketLocal(const char * path)153 EIBSocketLocal (const char *path)
154 {
155 EIBConnection *con = (EIBConnection *) malloc (sizeof (EIBConnection));
156 struct sockaddr_un addr;
157 if (!con)
158 {
159 errno = ENOMEM;
160 return 0;
161 }
162 addr.sun_family = AF_LOCAL;
163 strncpy (addr.sun_path, path, sizeof (addr.sun_path));
164 addr.sun_path[sizeof (addr.sun_path) - 1] = 0;
165
166 con->fd = socket (AF_LOCAL, SOCK_STREAM, 0);
167 con->ev = 0;
168 if (con->fd == -1)
169 {
170 free (con);
171 return 0;
172 }
173
174 if (pth_connect_ev (con->fd, (struct sockaddr *) &addr, sizeof (addr), con->ev) == -1)
175 {
176 int saveerr = errno;
177 close (con->fd);
178 free (con);
179 errno = saveerr;
180 return 0;
181 }
182 con->buflen = 0;
183 con->buf = 0;
184 con->readlen = 0;
185
186 return con;
187 }
188
189 EIBConnection *
EIBSocketRemote(const char * host,int port)190 EIBSocketRemote (const char *host, int port)
191 {
192 EIBConnection *con = (EIBConnection *) malloc (sizeof (EIBConnection));
193 struct sockaddr_in addr;
194 if (!con)
195 {
196 errno = ENOMEM;
197 return 0;
198 }
199
200 if (!GetHostIP (&addr, host))
201 {
202 free (con);
203 errno = ECONNREFUSED;
204 return 0;
205 }
206 addr.sin_port = htons (port);
207
208 con->fd = socket (addr.sin_family, SOCK_STREAM, 0);
209 con->ev = 0;
210 if (con->fd == -1)
211 {
212 free (con);
213 return 0;
214 }
215
216 if (pth_connect_ev (con->fd, (struct sockaddr *) &addr, sizeof (addr), con->ev) == -1)
217 {
218 int saveerr = errno;
219 close (con->fd);
220 free (con);
221 errno = saveerr;
222 return 0;
223 }
224 con->buflen = 0;
225 con->buf = 0;
226 con->readlen = 0;
227
228 return con;
229 }
230
231 EIBConnection *
EIBSocketURL(const char * url)232 EIBSocketURL (const char *url)
233 {
234 if (!url)
235 {
236 errno = EINVAL;
237 return 0;
238 }
239 if (!strncmp (url, "local:", 6))
240 {
241 return EIBSocketLocal (url + 6);
242 }
243 if (!strncmp (url, "ip:", 3))
244 {
245 char *a = strdup (url + 3);
246 char *b;
247 int port;
248 EIBConnection *c;
249 if (!a)
250 {
251 errno = ENOMEM;
252 return 0;
253 }
254 for (b = a; *b; b++)
255 if (*b == ':')
256 break;
257 if (*b == ':')
258 {
259 *b = 0;
260 port = atoi (b + 1);
261 }
262 else
263 port = 6720;
264 c = EIBSocketRemote (a, port);
265 free (a);
266 return c;
267 }
268 errno = EINVAL;
269 return 0;
270 }
271
272 /** send a request to eibd */
273 static int
SendRequest(EIBConnection * con,unsigned int size,uchar * data)274 SendRequest (EIBConnection * con, unsigned int size, uchar * data)
275 {
276 uchar head[2];
277 int i, start;
278
279 if (size > 0xffff || size < 2)
280 {
281 errno = EINVAL;
282 return -1;
283 }
284 head[0] = (size >> 8) & 0xff;
285 head[1] = (size) & 0xff;
286
287 lp1:
288 i = pth_write_ev (con->fd, &head, 2, con->ev);
289 if (i == -1 && errno == EINTR)
290 goto lp1;
291 if (i == -1)
292 return -1;
293 if (i != 2)
294 {
295 errno = ECONNRESET;
296 return -1;
297 }
298 start = 0;
299 lp2:
300 i = pth_write_ev (con->fd, data + start, size - start, con->ev);
301 if (i == -1 && errno == EINTR)
302 goto lp2;
303 if (i == -1)
304 return -1;
305 if (i == 0)
306 {
307 errno = ECONNRESET;
308 return -1;
309 }
310 start += i;
311 if (start < size)
312 goto lp2;
313 return 0;
314 }
315
316 static int
CheckRequest(EIBConnection * con)317 CheckRequest (EIBConnection * con)
318 {
319 int i;
320 if (con->readlen < 2)
321 {
322 uchar head[2];
323 head[0] = (con->size >> 8) & 0xff;
324 i = pth_read_ev (con->fd, &head + con->readlen, 2 - con->readlen, con->ev);
325 if (i == -1 && errno == EINTR && (pth_event_status (con->ev) != PTH_STATUS_OCCURRED))
326 return 0;
327 if (i == -1)
328 return -1;
329 if (i == 0)
330 {
331 errno = ECONNRESET;
332 return -1;
333 }
334 con->readlen += i;
335 con->size = (head[0] << 8) | (head[1]);
336 if (con->size < 2)
337 {
338 errno = ECONNRESET;
339 return -1;
340 }
341
342 if (con->size > con->buflen)
343 {
344 con->buf = (uchar *) realloc (con->buf, con->size);
345 if (con->buf == 0)
346 {
347 con->buflen = 0;
348 errno = ENOMEM;
349 return -1;
350 }
351 con->buflen = con->size;
352 }
353 return 0;
354 }
355
356 if (con->readlen < con->size + 2)
357 {
358 i =
359 pth_read_ev (con->fd, con->buf + (con->readlen - 2),
360 con->size - (con->readlen - 2), con->ev);
361 if (i == -1 && errno == EINTR)
362 return 0;
363 if (i == -1)
364 return -1;
365 if (i == 0)
366 {
367 errno = ECONNRESET;
368 return -1;
369 }
370 con->readlen += i;
371 }
372 return 0;
373 }
374
375 /** receive packet from eibd */
376 static int
GetRequest(EIBConnection * con)377 GetRequest (EIBConnection * con)
378 {
379 do
380 {
381 if (CheckRequest (con) == -1)
382 return -1;
383 }
384 while (con->readlen < 2
385 || (con->readlen >= 2 && con->readlen < con->size + 2));
386
387 con->readlen = 0;
388
389 return 0;
390 }
391
392 int
EIB_Poll_Complete(EIBConnection * con)393 EIB_Poll_Complete (EIBConnection * con)
394 {
395 if (!con)
396 {
397 errno = EINVAL;
398 return -1;
399 }
400 if (CheckRequest (con) == -1)
401 return -1;
402 return (con->readlen >= 2 && con->readlen >= con->size + 2) ? 1 : 0;
403 }
404
405 int
EIB_Poll_FD(EIBConnection * con)406 EIB_Poll_FD (EIBConnection * con)
407 {
408 if (!con)
409 {
410 errno = EINVAL;
411 return -1;
412 }
413 return con->fd;
414 }
415
416 int
EIBComplete(EIBConnection * con)417 EIBComplete (EIBConnection * con)
418 {
419 if (!con)
420 {
421 errno = EINVAL;
422 return -1;
423 }
424 return con->complete (con);
425 }
426
427 static int
OpenBusmonitor_complete(EIBConnection * con)428 OpenBusmonitor_complete (EIBConnection * con)
429 {
430 int i;
431 i = GetRequest (con);
432 if (i == -1)
433 return -1;
434
435 if (EIBTYPE (con) != EIB_OPEN_BUSMONITOR)
436 {
437 errno = ECONNRESET;
438 return -1;
439 }
440 return 0;
441 }
442
443 int
EIBOpenBusmonitor_async(EIBConnection * con)444 EIBOpenBusmonitor_async (EIBConnection * con)
445 {
446 uchar head[2];
447 int i;
448 if (!con)
449 {
450 errno = EINVAL;
451 return -1;
452 }
453 EIBSETTYPE (head, EIB_OPEN_BUSMONITOR);
454 i = SendRequest (con, 2, head);
455 if (i == -1)
456 return -1;
457
458 con->complete = OpenBusmonitor_complete;
459 return 0;
460 }
461
462 int
EIBOpenBusmonitor(EIBConnection * con)463 EIBOpenBusmonitor (EIBConnection * con)
464 {
465 if (EIBOpenBusmonitor_async (con) == -1)
466 return -1;
467 return EIBComplete (con);
468 }
469
470 static int
OpenBusmonitorText_complete(EIBConnection * con)471 OpenBusmonitorText_complete (EIBConnection * con)
472 {
473 int i;
474 i = GetRequest (con);
475 if (i == -1)
476 return -1;
477
478 if (EIBTYPE (con) != EIB_OPEN_BUSMONITOR_TEXT)
479 {
480 errno = ECONNRESET;
481 return -1;
482 }
483 return 0;
484 }
485
486 int
EIBOpenBusmonitorText_async(EIBConnection * con)487 EIBOpenBusmonitorText_async (EIBConnection * con)
488 {
489 uchar head[2];
490 int i;
491 if (!con)
492 {
493 errno = EINVAL;
494 return -1;
495 }
496 EIBSETTYPE (head, EIB_OPEN_BUSMONITOR_TEXT);
497 i = SendRequest (con, 2, head);
498 if (i == -1)
499 return -1;
500 con->complete = OpenBusmonitorText_complete;
501 return 0;
502 }
503
504 int
EIBOpenBusmonitorText(EIBConnection * con)505 EIBOpenBusmonitorText (EIBConnection * con)
506 {
507 if (EIBOpenBusmonitorText_async (con) == -1)
508 return -1;
509 return EIBComplete (con);
510 }
511
512 static int
OpenVBusmonitor_complete(EIBConnection * con)513 OpenVBusmonitor_complete (EIBConnection * con)
514 {
515 int i;
516 i = GetRequest (con);
517 if (i == -1)
518 return -1;
519
520 if (EIBTYPE (con) != EIB_OPEN_VBUSMONITOR)
521 {
522 errno = ECONNRESET;
523 return -1;
524 }
525 return 0;
526 }
527
528 int
EIBOpenVBusmonitor_async(EIBConnection * con)529 EIBOpenVBusmonitor_async (EIBConnection * con)
530 {
531 uchar head[2];
532 int i;
533 if (!con)
534 {
535 errno = EINVAL;
536 return -1;
537 }
538 EIBSETTYPE (head, EIB_OPEN_VBUSMONITOR);
539 i = SendRequest (con, 2, head);
540 if (i == -1)
541 return -1;
542 con->complete = OpenVBusmonitor_complete;
543 return 0;
544 }
545
546 int
EIBOpenVBusmonitor(EIBConnection * con)547 EIBOpenVBusmonitor (EIBConnection * con)
548 {
549 if (EIBOpenVBusmonitor_async (con) == -1)
550 return -1;
551 return EIBComplete (con);
552 }
553
554 static int
OpenVBusmonitorText_complete(EIBConnection * con)555 OpenVBusmonitorText_complete (EIBConnection * con)
556 {
557 int i;
558 i = GetRequest (con);
559 if (i == -1)
560 return -1;
561
562 if (EIBTYPE (con) != EIB_OPEN_VBUSMONITOR_TEXT)
563 {
564 errno = ECONNRESET;
565 return -1;
566 }
567 return 0;
568 }
569
570 int
EIBOpenVBusmonitorText_async(EIBConnection * con)571 EIBOpenVBusmonitorText_async (EIBConnection * con)
572 {
573 uchar head[2];
574 int i;
575 if (!con)
576 {
577 errno = EINVAL;
578 return -1;
579 }
580 EIBSETTYPE (head, EIB_OPEN_VBUSMONITOR_TEXT);
581 i = SendRequest (con, 2, head);
582 if (i == -1)
583 return -1;
584 con->complete = OpenVBusmonitorText_complete;
585 return 0;
586 }
587
588 int
EIBOpenVBusmonitorText(EIBConnection * con)589 EIBOpenVBusmonitorText (EIBConnection * con)
590 {
591 if (EIBOpenVBusmonitorText_async (con) == -1)
592 return -1;
593 return EIBComplete (con);
594 }
595
596 int
EIBGetBusmonitorPacket(EIBConnection * con,int maxlen,uint8_t * buf)597 EIBGetBusmonitorPacket (EIBConnection * con, int maxlen, uint8_t * buf)
598 {
599 int i;
600 if (!con || !buf)
601 {
602 errno = EINVAL;
603 return -1;
604 }
605
606 i = GetRequest (con);
607 if (i == -1)
608 return -1;
609
610 if (EIBTYPE (con) != EIB_BUSMONITOR_PACKET)
611 {
612 errno = ECONNRESET;
613 return -1;
614 }
615 i = con->size - 2;
616 if (i > maxlen)
617 i = maxlen;
618 memcpy (buf, con->buf + 2, i);
619 return i;
620 }
621
622 static int
OpenT_Connection_complete(EIBConnection * con)623 OpenT_Connection_complete (EIBConnection * con)
624 {
625 int i;
626 i = GetRequest (con);
627 if (i == -1)
628 return -1;
629
630 if (EIBTYPE (con) != EIB_OPEN_T_CONNECTION)
631 {
632 errno = ECONNRESET;
633 return -1;
634 }
635 return 0;
636 }
637
638 int
EIBOpenT_Connection_async(EIBConnection * con,eibaddr_t dest)639 EIBOpenT_Connection_async (EIBConnection * con, eibaddr_t dest)
640 {
641 uchar head[5];
642 int i;
643 if (!con)
644 {
645 errno = EINVAL;
646 return -1;
647 }
648 EIBSETTYPE (head, EIB_OPEN_T_CONNECTION);
649 EIBSETADDR (head + 2, dest);
650 i = SendRequest (con, 5, head);
651 if (i == -1)
652 return -1;
653 con->complete = OpenT_Connection_complete;
654 return 0;
655 }
656
657 int
EIBOpenT_Connection(EIBConnection * con,eibaddr_t dest)658 EIBOpenT_Connection (EIBConnection * con, eibaddr_t dest)
659 {
660 if (EIBOpenT_Connection_async (con, dest) == -1)
661 return -1;
662 return EIBComplete (con);
663 }
664
665 static int
OpenT_TPDU_complete(EIBConnection * con)666 OpenT_TPDU_complete (EIBConnection * con)
667 {
668 int i;
669 i = GetRequest (con);
670 if (i == -1)
671 return -1;
672
673 if (EIBTYPE (con) != EIB_OPEN_T_TPDU)
674 {
675 errno = ECONNRESET;
676 return -1;
677 }
678 return 0;
679 }
680
681 int
EIBOpenT_TPDU_async(EIBConnection * con,eibaddr_t src)682 EIBOpenT_TPDU_async (EIBConnection * con, eibaddr_t src)
683 {
684 uchar head[5];
685 int i;
686 if (!con)
687 {
688 errno = EINVAL;
689 return -1;
690 }
691 EIBSETTYPE (head, EIB_OPEN_T_TPDU);
692 EIBSETADDR (head + 2, src);
693 i = SendRequest (con, 5, head);
694 if (i == -1)
695 return -1;
696 con->complete = OpenT_TPDU_complete;
697 return 0;
698 }
699
700 int
EIBOpenT_TPDU(EIBConnection * con,eibaddr_t src)701 EIBOpenT_TPDU (EIBConnection * con, eibaddr_t src)
702 {
703 if (EIBOpenT_TPDU_async (con, src) == -1)
704 return -1;
705 return EIBComplete (con);
706 }
707
708 static int
OpenT_Individual_complete(EIBConnection * con)709 OpenT_Individual_complete (EIBConnection * con)
710 {
711 int i;
712 i = GetRequest (con);
713 if (i == -1)
714 return -1;
715
716 if (EIBTYPE (con) != EIB_OPEN_T_INDIVIDUAL)
717 {
718 errno = ECONNRESET;
719 return -1;
720 }
721 return 0;
722 }
723
724 int
EIBOpenT_Individual_async(EIBConnection * con,eibaddr_t dest,int write_only)725 EIBOpenT_Individual_async (EIBConnection * con, eibaddr_t dest,
726 int write_only)
727 {
728 uchar head[5];
729 int i;
730 if (!con)
731 {
732 errno = EINVAL;
733 return -1;
734 }
735 EIBSETTYPE (head, EIB_OPEN_T_INDIVIDUAL);
736 EIBSETADDR (head + 2, dest);
737 head[4] = (write_only ? 0xff : 0);
738 i = SendRequest (con, 5, head);
739 if (i == -1)
740 return -1;
741 con->complete = OpenT_Individual_complete;
742 return 0;
743 }
744
745 int
EIBOpenT_Individual(EIBConnection * con,eibaddr_t dest,int write_only)746 EIBOpenT_Individual (EIBConnection * con, eibaddr_t dest, int write_only)
747 {
748 if (EIBOpenT_Individual_async (con, dest, write_only) == -1)
749 return -1;
750 return EIBComplete (con);
751 }
752
753 static int
OpenT_Group_complete(EIBConnection * con)754 OpenT_Group_complete (EIBConnection * con)
755 {
756 int i;
757 i = GetRequest (con);
758 if (i == -1)
759 return -1;
760
761 if (EIBTYPE (con) != EIB_OPEN_T_GROUP)
762 {
763 errno = ECONNRESET;
764 return -1;
765 }
766 return 0;
767 }
768
769 int
EIBOpenT_Group_async(EIBConnection * con,eibaddr_t dest,int write_only)770 EIBOpenT_Group_async (EIBConnection * con, eibaddr_t dest, int write_only)
771 {
772 uchar head[5];
773 int i;
774 if (!con)
775 {
776 errno = EINVAL;
777 return -1;
778 }
779 EIBSETTYPE (head, EIB_OPEN_T_GROUP);
780 EIBSETADDR (head + 2, dest);
781 head[4] = (write_only ? 0xff : 0);
782 i = SendRequest (con, 5, head);
783 if (i == -1)
784 return -1;
785 con->complete = OpenT_Group_complete;
786 return 0;
787 }
788
789 int
EIBOpenT_Group(EIBConnection * con,eibaddr_t dest,int write_only)790 EIBOpenT_Group (EIBConnection * con, eibaddr_t dest, int write_only)
791 {
792 if (EIBOpenT_Group_async (con, dest, write_only) == -1)
793 return -1;
794 return EIBComplete (con);
795 }
796
797 static int
OpenT_Broadcast_complete(EIBConnection * con)798 OpenT_Broadcast_complete (EIBConnection * con)
799 {
800 int i;
801 i = GetRequest (con);
802 if (i == -1)
803 return -1;
804
805 if (EIBTYPE (con) != EIB_OPEN_T_BROADCAST)
806 {
807 errno = ECONNRESET;
808 return -1;
809 }
810 return 0;
811 }
812
813 int
EIBOpenT_Broadcast_async(EIBConnection * con,int write_only)814 EIBOpenT_Broadcast_async (EIBConnection * con, int write_only)
815 {
816 uchar head[5];
817 int i;
818 if (!con)
819 {
820 errno = EINVAL;
821 return -1;
822 }
823 EIBSETTYPE (head, EIB_OPEN_T_BROADCAST);
824 head[4] = (write_only ? 0xff : 0);
825 i = SendRequest (con, 5, head);
826 if (i == -1)
827 return -1;
828 con->complete = OpenT_Broadcast_complete;
829 return 0;
830 }
831
832 int
EIBOpenT_Broadcast(EIBConnection * con,int write_only)833 EIBOpenT_Broadcast (EIBConnection * con, int write_only)
834 {
835 if (EIBOpenT_Broadcast_async (con, write_only) == -1)
836 return -1;
837 return EIBComplete (con);
838 }
839
840 int
EIBSendTPDU(EIBConnection * con,eibaddr_t dest,int len,uint8_t * data)841 EIBSendTPDU (EIBConnection * con, eibaddr_t dest, int len, uint8_t * data)
842 {
843 uchar *ibuf;
844 int i;
845 if (!con)
846 {
847 errno = EINVAL;
848 return -1;
849 }
850 if (len < 2 || !data)
851 {
852 errno = EINVAL;
853 return -1;
854 }
855 ibuf = (uchar *) malloc (len + 4);
856 if (!ibuf)
857 {
858 errno = ENOMEM;
859 return -1;
860 }
861 EIBSETTYPE (ibuf, EIB_APDU_PACKET);
862 EIBSETADDR (ibuf + 2, dest);
863 memcpy (ibuf + 4, data, len);
864 i = SendRequest (con, len + 4, ibuf);
865 free (ibuf);
866 return i;
867 }
868
869 int
EIBSendAPDU(EIBConnection * con,int len,uint8_t * data)870 EIBSendAPDU (EIBConnection * con, int len, uint8_t * data)
871 {
872 uchar *ibuf;
873 int i;
874 if (!con)
875 {
876 errno = EINVAL;
877 return -1;
878 }
879 if (len < 2 || !data)
880 {
881 errno = EINVAL;
882 return -1;
883 }
884 ibuf = (uchar *) malloc (len + 2);
885 if (!ibuf)
886 {
887 errno = ENOMEM;
888 return -1;
889 }
890 EIBSETTYPE (ibuf, EIB_APDU_PACKET);
891 memcpy (ibuf + 2, data, len);
892 i = SendRequest (con, len + 2, ibuf);
893 free (ibuf);
894 return i;
895 }
896
897 int
EIBGetAPDU(EIBConnection * con,int maxlen,uint8_t * buf)898 EIBGetAPDU (EIBConnection * con, int maxlen, uint8_t * buf)
899 {
900 int i;
901 if (!con || !buf)
902 {
903 errno = EINVAL;
904 return -1;
905 }
906
907 i = GetRequest (con);
908 if (i == -1)
909 return -1;
910
911 if (EIBTYPE (con) != EIB_APDU_PACKET)
912 {
913 errno = ECONNRESET;
914 return -1;
915 }
916 i = con->size - 2;
917 if (i > maxlen)
918 i = maxlen;
919 memcpy (buf, con->buf + 2, i);
920 return i;
921 }
922
923 int
EIBGetAPDU_Src(EIBConnection * con,int maxlen,uint8_t * buf,eibaddr_t * src)924 EIBGetAPDU_Src (EIBConnection * con, int maxlen, uint8_t * buf,
925 eibaddr_t * src)
926 {
927 int i;
928 if (!con || !buf)
929 {
930 errno = EINVAL;
931 return -1;
932 }
933
934 i = GetRequest (con);
935 if (i == -1)
936 return -1;
937
938 if (EIBTYPE (con) != EIB_APDU_PACKET || con->size < 4)
939 {
940 errno = ECONNRESET;
941 return -1;
942 }
943 i = con->size - 4;
944 if (i > maxlen)
945 i = maxlen;
946 memcpy (buf, con->buf + 4, i);
947 if (src)
948 *src = (con->buf[2] << 8) | (con->buf[3]);
949 return i;
950 }
951
952 static int
Open_GroupSocket_complete(EIBConnection * con)953 Open_GroupSocket_complete (EIBConnection * con)
954 {
955 int i;
956 i = GetRequest (con);
957 if (i == -1)
958 return -1;
959
960 if (EIBTYPE (con) != EIB_OPEN_GROUPCON)
961 {
962 errno = ECONNRESET;
963 return -1;
964 }
965 return 0;
966 }
967
968 int
EIBOpen_GroupSocket_async(EIBConnection * con,int write_only)969 EIBOpen_GroupSocket_async (EIBConnection * con, int write_only)
970 {
971 uchar head[5];
972 int i;
973 if (!con)
974 {
975 errno = EINVAL;
976 return -1;
977 }
978 EIBSETTYPE (head, EIB_OPEN_GROUPCON);
979 head[4] = (write_only ? 0xff : 0);
980 i = SendRequest (con, 5, head);
981 if (i == -1)
982 return -1;
983 con->complete = Open_GroupSocket_complete;
984 return 0;
985 }
986
987 int
EIBOpen_GroupSocket(EIBConnection * con,int write_only)988 EIBOpen_GroupSocket (EIBConnection * con, int write_only)
989 {
990 if (EIBOpen_GroupSocket_async (con, write_only) == -1)
991 return -1;
992 return EIBComplete (con);
993 }
994
995 int
EIBGetGroup_Src(EIBConnection * con,int maxlen,uint8_t * buf,eibaddr_t * src,eibaddr_t * dest)996 EIBGetGroup_Src (EIBConnection * con, int maxlen, uint8_t * buf,
997 eibaddr_t * src, eibaddr_t * dest)
998 {
999 int i;
1000 if (!con || !buf)
1001 {
1002 errno = EINVAL;
1003 return -1;
1004 }
1005
1006 i = GetRequest (con);
1007 if (i == -1)
1008 return -1;
1009
1010 if (EIBTYPE (con) != EIB_GROUP_PACKET || con->size < 6)
1011 {
1012 errno = ECONNRESET;
1013 return -1;
1014 }
1015 i = con->size - 6;
1016 if (i > maxlen)
1017 i = maxlen;
1018 memcpy (buf, con->buf + 6, i);
1019 if (src)
1020 *src = (con->buf[2] << 8) | (con->buf[3]);
1021 if (dest)
1022 *dest = (con->buf[4] << 8) | (con->buf[5]);
1023 return i;
1024 }
1025
1026 int
EIBSendGroup(EIBConnection * con,eibaddr_t dest,int len,uint8_t * data)1027 EIBSendGroup (EIBConnection * con, eibaddr_t dest, int len, uint8_t * data)
1028 {
1029 uchar *ibuf;
1030 int i;
1031 if (!con)
1032 {
1033 errno = EINVAL;
1034 return -1;
1035 }
1036 if (len < 2 || !data)
1037 {
1038 errno = EINVAL;
1039 return -1;
1040 }
1041 ibuf = (uchar *) malloc (len + 4);
1042 if (!ibuf)
1043 {
1044 errno = ENOMEM;
1045 return -1;
1046 }
1047 EIBSETTYPE (ibuf, EIB_GROUP_PACKET);
1048 EIBSETADDR (ibuf + 2, dest);
1049 memcpy (ibuf + 4, data, len);
1050 i = SendRequest (con, len + 4, ibuf);
1051 free (ibuf);
1052 return i;
1053 }
1054
1055 static int
M_ReadIndividualAddresses_complete(EIBConnection * con)1056 M_ReadIndividualAddresses_complete (EIBConnection * con)
1057 {
1058 int i;
1059 i = GetRequest (con);
1060 if (i == -1)
1061 return -1;
1062 if (EIBTYPE (con) != EIB_M_INDIVIDUAL_ADDRESS_READ)
1063 {
1064 errno = ECONNRESET;
1065 return -1;
1066 }
1067 i = con->size - 2;
1068 if (i > con->req.len)
1069 i = con->req.len;
1070 memcpy (con->req.buf, con->buf + 2, i);
1071 return i;
1072 }
1073
1074 int
EIB_M_ReadIndividualAddresses_async(EIBConnection * con,int maxlen,uint8_t * buf)1075 EIB_M_ReadIndividualAddresses_async (EIBConnection * con, int maxlen,
1076 uint8_t * buf)
1077 {
1078 uchar head[2];
1079 if (!con)
1080 {
1081 errno = EINVAL;
1082 return -1;
1083 }
1084 con->req.len = maxlen;
1085 con->req.buf = buf;
1086 EIBSETTYPE (head, EIB_M_INDIVIDUAL_ADDRESS_READ);
1087 if (SendRequest (con, 2, head) == -1)
1088 return -1;
1089 con->complete = M_ReadIndividualAddresses_complete;
1090 return 0;
1091 }
1092
1093 int
EIB_M_ReadIndividualAddresses(EIBConnection * con,int maxlen,uint8_t * buf)1094 EIB_M_ReadIndividualAddresses (EIBConnection * con, int maxlen, uint8_t * buf)
1095 {
1096 if (EIB_M_ReadIndividualAddresses_async (con, maxlen, buf) == -1)
1097 return -1;
1098 return EIBComplete (con);
1099 }
1100
1101 static int
M_Progmode_On_complete(EIBConnection * con)1102 M_Progmode_On_complete (EIBConnection * con)
1103 {
1104 int i;
1105 i = GetRequest (con);
1106 if (i == -1)
1107 return -1;
1108 if (EIBTYPE (con) != EIB_PROG_MODE)
1109 {
1110 errno = ECONNRESET;
1111 return -1;
1112 }
1113 return 0;
1114 }
1115
1116 int
EIB_M_Progmode_On_async(EIBConnection * con,eibaddr_t dest)1117 EIB_M_Progmode_On_async (EIBConnection * con, eibaddr_t dest)
1118 {
1119 uchar head[5];
1120 if (!con)
1121 {
1122 errno = EINVAL;
1123 return -1;
1124 }
1125 EIBSETTYPE (head, EIB_PROG_MODE);
1126 EIBSETADDR (head + 2, dest);
1127 head[4] = 1;
1128 if (SendRequest (con, 5, head) == -1)
1129 return -1;
1130 con->complete = M_Progmode_On_complete;
1131 return 0;
1132 }
1133
1134 int
EIB_M_Progmode_On(EIBConnection * con,eibaddr_t dest)1135 EIB_M_Progmode_On (EIBConnection * con, eibaddr_t dest)
1136 {
1137 if (EIB_M_Progmode_On_async (con, dest) == -1)
1138 return -1;
1139 return EIBComplete (con);
1140 }
1141
1142 static int
M_Progmode_Off_complete(EIBConnection * con)1143 M_Progmode_Off_complete (EIBConnection * con)
1144 {
1145 int i;
1146 i = GetRequest (con);
1147 if (i == -1)
1148 return -1;
1149 if (EIBTYPE (con) != EIB_PROG_MODE)
1150 {
1151 errno = ECONNRESET;
1152 return -1;
1153 }
1154 return 0;
1155 }
1156
1157 int
EIB_M_Progmode_Off_async(EIBConnection * con,eibaddr_t dest)1158 EIB_M_Progmode_Off_async (EIBConnection * con, eibaddr_t dest)
1159 {
1160 uchar head[5];
1161 if (!con)
1162 {
1163 errno = EINVAL;
1164 return -1;
1165 }
1166 EIBSETTYPE (head, EIB_PROG_MODE);
1167 EIBSETADDR (head + 2, dest);
1168 head[4] = 0;
1169 if (SendRequest (con, 5, head) == -1)
1170 return -1;
1171 con->complete = M_Progmode_Off_complete;
1172 return 0;
1173 }
1174
1175 int
EIB_M_Progmode_Off(EIBConnection * con,eibaddr_t dest)1176 EIB_M_Progmode_Off (EIBConnection * con, eibaddr_t dest)
1177 {
1178 if (EIB_M_Progmode_Off_async (con, dest) == -1)
1179 return -1;
1180 return EIBComplete (con);
1181 }
1182
1183 static int
M_Progmode_Toggle_complete(EIBConnection * con)1184 M_Progmode_Toggle_complete (EIBConnection * con)
1185 {
1186 int i;
1187 i = GetRequest (con);
1188 if (i == -1)
1189 return -1;
1190 if (EIBTYPE (con) != EIB_PROG_MODE)
1191 {
1192 errno = ECONNRESET;
1193 return -1;
1194 }
1195 return 0;
1196 }
1197
1198 int
EIB_M_Progmode_Toggle_async(EIBConnection * con,eibaddr_t dest)1199 EIB_M_Progmode_Toggle_async (EIBConnection * con, eibaddr_t dest)
1200 {
1201 uchar head[5];
1202 if (!con)
1203 {
1204 errno = EINVAL;
1205 return -1;
1206 }
1207 EIBSETTYPE (head, EIB_PROG_MODE);
1208 EIBSETADDR (head + 2, dest);
1209 head[4] = 2;
1210 if (SendRequest (con, 5, head) == -1)
1211 return -1;
1212 con->complete = M_Progmode_Toggle_complete;
1213 return 0;
1214 }
1215
1216 int
EIB_M_Progmode_Toggle(EIBConnection * con,eibaddr_t dest)1217 EIB_M_Progmode_Toggle (EIBConnection * con, eibaddr_t dest)
1218 {
1219 if (EIB_M_Progmode_Toggle (con, dest) == -1)
1220 return -1;
1221 return EIBComplete (con);
1222 }
1223
1224 static int
M_Progmode_Status_complete(EIBConnection * con)1225 M_Progmode_Status_complete (EIBConnection * con)
1226 {
1227 int i;
1228 i = GetRequest (con);
1229 if (i == -1)
1230 return -1;
1231 if (EIBTYPE (con) != EIB_PROG_MODE || con->size < 3)
1232 {
1233 errno = ECONNRESET;
1234 return -1;
1235 }
1236 return con->buf[2];
1237 }
1238
1239 int
EIB_M_Progmode_Status_async(EIBConnection * con,eibaddr_t dest)1240 EIB_M_Progmode_Status_async (EIBConnection * con, eibaddr_t dest)
1241 {
1242 uchar head[5];
1243 if (!con)
1244 {
1245 errno = EINVAL;
1246 return -1;
1247 }
1248 EIBSETTYPE (head, EIB_PROG_MODE);
1249 EIBSETADDR (head + 2, dest);
1250 head[4] = 3;
1251 if (SendRequest (con, 5, head) == -1)
1252 return -1;
1253 con->complete = M_Progmode_Status_complete;
1254 return 0;
1255 }
1256
1257 int
EIB_M_Progmode_Status(EIBConnection * con,eibaddr_t dest)1258 EIB_M_Progmode_Status (EIBConnection * con, eibaddr_t dest)
1259 {
1260 if (EIB_M_Progmode_Status (con, dest) == -1)
1261 return -1;
1262 return EIBComplete (con);
1263 }
1264
1265 static int
M_GetMaskVersion_complete(EIBConnection * con)1266 M_GetMaskVersion_complete (EIBConnection * con)
1267 {
1268 int i;
1269 i = GetRequest (con);
1270 if (i == -1)
1271 return -1;
1272 if (EIBTYPE (con) != EIB_MASK_VERSION || con->size < 4)
1273 {
1274 errno = ECONNRESET;
1275 return -1;
1276 }
1277 return (con->buf[2] << 8) | (con->buf[3]);
1278 }
1279
1280 int
EIB_M_GetMaskVersion_async(EIBConnection * con,eibaddr_t dest)1281 EIB_M_GetMaskVersion_async (EIBConnection * con, eibaddr_t dest)
1282 {
1283 uchar head[4];
1284 if (!con)
1285 {
1286 errno = EINVAL;
1287 return -1;
1288 }
1289 EIBSETTYPE (head, EIB_MASK_VERSION);
1290 EIBSETADDR (head + 2, dest);
1291 if (SendRequest (con, 4, head) == -1)
1292 return -1;
1293 con->complete = M_GetMaskVersion_complete;
1294 return 0;
1295 }
1296
1297 int
EIB_M_GetMaskVersion(EIBConnection * con,eibaddr_t dest)1298 EIB_M_GetMaskVersion (EIBConnection * con, eibaddr_t dest)
1299 {
1300 if (EIB_M_GetMaskVersion_async (con, dest) == -1)
1301 return -1;
1302 return EIBComplete (con);
1303 }
1304
1305 static int
M_WriteIndividualAddress_complete(EIBConnection * con)1306 M_WriteIndividualAddress_complete (EIBConnection * con)
1307 {
1308 int i;
1309 i = GetRequest (con);
1310 if (i == -1)
1311 return -1;
1312 if (EIBTYPE (con) == EIB_ERROR_ADDR_EXISTS)
1313 {
1314 errno = EADDRINUSE;
1315 return -1;
1316 }
1317 if (EIBTYPE (con) == EIB_M_INDIVIDUAL_ADDRESS_WRITE)
1318 {
1319 return 0;
1320 }
1321 if (EIBTYPE (con) == EIB_ERROR_TIMEOUT)
1322 {
1323 errno = ETIMEDOUT;
1324 return -1;
1325 }
1326 if (EIBTYPE (con) == EIB_ERROR_MORE_DEVICE)
1327 {
1328 errno = EADDRNOTAVAIL;
1329 return -1;
1330 }
1331 errno = ECONNRESET;
1332 return -1;
1333 }
1334
1335 int
EIB_M_WriteIndividualAddress_async(EIBConnection * con,eibaddr_t dest)1336 EIB_M_WriteIndividualAddress_async (EIBConnection * con, eibaddr_t dest)
1337 {
1338 uchar head[4];
1339 if (!con)
1340 {
1341 errno = EINVAL;
1342 return -1;
1343 }
1344 EIBSETTYPE (head, EIB_M_INDIVIDUAL_ADDRESS_WRITE);
1345 EIBSETADDR (head + 2, dest);
1346 if (SendRequest (con, 4, head) == -1)
1347 return -1;
1348 con->complete = M_WriteIndividualAddress_complete;
1349 return 0;
1350 }
1351
1352 int
EIB_M_WriteIndividualAddress(EIBConnection * con,eibaddr_t dest)1353 EIB_M_WriteIndividualAddress (EIBConnection * con, eibaddr_t dest)
1354 {
1355 if (EIB_M_WriteIndividualAddress_async (con, dest) == -1)
1356 return -1;
1357 return EIBComplete (con);
1358 }
1359
1360 static int
MC_Connect_complete(EIBConnection * con)1361 MC_Connect_complete (EIBConnection * con)
1362 {
1363 int i;
1364 i = GetRequest (con);
1365 if (i == -1)
1366 return -1;
1367
1368 if (EIBTYPE (con) != EIB_MC_CONNECTION)
1369 {
1370 errno = ECONNRESET;
1371 return -1;
1372 }
1373 return 0;
1374 }
1375
1376 int
EIB_MC_Connect_async(EIBConnection * con,eibaddr_t dest)1377 EIB_MC_Connect_async (EIBConnection * con, eibaddr_t dest)
1378 {
1379 uchar head[4];
1380 int i;
1381 if (!con)
1382 {
1383 errno = EINVAL;
1384 return -1;
1385 }
1386 EIBSETTYPE (head, EIB_MC_CONNECTION);
1387 EIBSETADDR (head + 2, dest);
1388 i = SendRequest (con, 4, head);
1389 if (i == -1)
1390 return -1;
1391
1392 con->complete = MC_Connect_complete;
1393 return 0;
1394 }
1395
1396 int
EIB_MC_Connect(EIBConnection * con,eibaddr_t dest)1397 EIB_MC_Connect (EIBConnection * con, eibaddr_t dest)
1398 {
1399 if (EIB_MC_Connect_async (con, dest) == -1)
1400 return -1;
1401 return EIBComplete (con);
1402 }
1403
1404 static int
MC_Progmode_On_complete(EIBConnection * con)1405 MC_Progmode_On_complete (EIBConnection * con)
1406 {
1407 int i;
1408 i = GetRequest (con);
1409 if (i == -1)
1410 return -1;
1411 if (EIBTYPE (con) != EIB_MC_PROG_MODE)
1412 {
1413 errno = ECONNRESET;
1414 return -1;
1415 }
1416 return 0;
1417 }
1418
1419 int
EIB_MC_Progmode_On_async(EIBConnection * con)1420 EIB_MC_Progmode_On_async (EIBConnection * con)
1421 {
1422 uchar head[3];
1423 if (!con)
1424 {
1425 errno = EINVAL;
1426 return -1;
1427 }
1428 EIBSETTYPE (head, EIB_MC_PROG_MODE);
1429 head[2] = 1;
1430 if (SendRequest (con, 3, head) == -1)
1431 return -1;
1432 con->complete = MC_Progmode_On_complete;
1433 return 0;
1434 }
1435
1436 int
EIB_MC_Progmode_On(EIBConnection * con)1437 EIB_MC_Progmode_On (EIBConnection * con)
1438 {
1439 if (EIB_MC_Progmode_On_async (con) == -1)
1440 return -1;
1441 return EIBComplete (con);
1442 }
1443
1444 static int
MC_Progmode_Off_complete(EIBConnection * con)1445 MC_Progmode_Off_complete (EIBConnection * con)
1446 {
1447 int i;
1448 i = GetRequest (con);
1449 if (i == -1)
1450 return -1;
1451 if (EIBTYPE (con) != EIB_MC_PROG_MODE)
1452 {
1453 errno = ECONNRESET;
1454 return -1;
1455 }
1456 return 0;
1457 }
1458
1459 int
EIB_MC_Progmode_Off_async(EIBConnection * con)1460 EIB_MC_Progmode_Off_async (EIBConnection * con)
1461 {
1462 uchar head[3];
1463 if (!con)
1464 {
1465 errno = EINVAL;
1466 return -1;
1467 }
1468 EIBSETTYPE (head, EIB_MC_PROG_MODE);
1469 head[2] = 0;
1470 if (SendRequest (con, 3, head) == -1)
1471 return -1;
1472 con->complete = MC_Progmode_Off_complete;
1473 return 0;
1474 }
1475
1476 int
EIB_MC_Progmode_Off(EIBConnection * con)1477 EIB_MC_Progmode_Off (EIBConnection * con)
1478 {
1479 if (EIB_MC_Progmode_Off_async (con) == -1)
1480 return -1;
1481 return EIBComplete (con);
1482 }
1483
1484 static int
MC_Progmode_Toggle_complete(EIBConnection * con)1485 MC_Progmode_Toggle_complete (EIBConnection * con)
1486 {
1487 int i;
1488 i = GetRequest (con);
1489 if (i == -1)
1490 return -1;
1491 if (EIBTYPE (con) != EIB_MC_PROG_MODE)
1492 {
1493 errno = ECONNRESET;
1494 return -1;
1495 }
1496 return 0;
1497 }
1498
1499 int
EIB_MC_Progmode_Toggle_async(EIBConnection * con)1500 EIB_MC_Progmode_Toggle_async (EIBConnection * con)
1501 {
1502 uchar head[3];
1503 if (!con)
1504 {
1505 errno = EINVAL;
1506 return -1;
1507 }
1508 EIBSETTYPE (head, EIB_MC_PROG_MODE);
1509 head[2] = 2;
1510 if (SendRequest (con, 3, head) == -1)
1511 return -1;
1512 con->complete = MC_Progmode_Toggle_complete;
1513 return 0;
1514 }
1515
1516 int
EIB_MC_Progmode_Toggle(EIBConnection * con)1517 EIB_MC_Progmode_Toggle (EIBConnection * con)
1518 {
1519 if (EIB_MC_Progmode_Toggle_async (con) == -1)
1520 return -1;
1521 return EIBComplete (con);
1522 }
1523
1524 static int
MC_Progmode_Status_complete(EIBConnection * con)1525 MC_Progmode_Status_complete (EIBConnection * con)
1526 {
1527 int i;
1528 i = GetRequest (con);
1529 if (i == -1)
1530 return -1;
1531 if (EIBTYPE (con) != EIB_MC_PROG_MODE || con->size < 3)
1532 {
1533 errno = ECONNRESET;
1534 return -1;
1535 }
1536 return con->buf[2];
1537 }
1538
1539 int
EIB_MC_Progmode_Status_async(EIBConnection * con)1540 EIB_MC_Progmode_Status_async (EIBConnection * con)
1541 {
1542 uchar head[3];
1543 if (!con)
1544 {
1545 errno = EINVAL;
1546 return -1;
1547 }
1548 EIBSETTYPE (head, EIB_MC_PROG_MODE);
1549 head[2] = 3;
1550 if (SendRequest (con, 3, head) == -1)
1551 return -1;
1552 con->complete = MC_Progmode_Status_complete;
1553 return 0;
1554 }
1555
1556 int
EIB_MC_Progmode_Status(EIBConnection * con)1557 EIB_MC_Progmode_Status (EIBConnection * con)
1558 {
1559 if (EIB_MC_Progmode_Status_async (con) == -1)
1560 return -1;
1561 return EIBComplete (con);
1562 }
1563
1564 static int
MC_GetMaskVersion_complete(EIBConnection * con)1565 MC_GetMaskVersion_complete (EIBConnection * con)
1566 {
1567 int i;
1568 i = GetRequest (con);
1569 if (i == -1)
1570 return -1;
1571 if (EIBTYPE (con) != EIB_MC_MASK_VERSION || con->size < 4)
1572 {
1573 errno = ECONNRESET;
1574 return -1;
1575 }
1576 return (con->buf[2] << 8) | (con->buf[3]);
1577 }
1578
1579 int
EIB_MC_GetMaskVersion_async(EIBConnection * con)1580 EIB_MC_GetMaskVersion_async (EIBConnection * con)
1581 {
1582 uchar head[2];
1583 if (!con)
1584 {
1585 errno = EINVAL;
1586 return -1;
1587 }
1588 EIBSETTYPE (head, EIB_MC_MASK_VERSION);
1589 if (SendRequest (con, 2, head) == -1)
1590 return -1;
1591 con->complete = MC_GetMaskVersion_complete;
1592 return 0;
1593 }
1594
1595 int
EIB_MC_GetMaskVersion(EIBConnection * con)1596 EIB_MC_GetMaskVersion (EIBConnection * con)
1597 {
1598 if (EIB_MC_GetMaskVersion_async (con) == -1)
1599 return -1;
1600 return EIBComplete (con);
1601 }
1602
1603 static int
MC_GetPEIType_complete(EIBConnection * con)1604 MC_GetPEIType_complete (EIBConnection * con)
1605 {
1606 int i;
1607 i = GetRequest (con);
1608 if (i == -1)
1609 return -1;
1610 if (EIBTYPE (con) != EIB_MC_PEI_TYPE || con->size < 4)
1611 {
1612 errno = ECONNRESET;
1613 return -1;
1614 }
1615 return (con->buf[2] << 8) | (con->buf[3]);
1616 }
1617
1618 int
EIB_MC_GetPEIType_async(EIBConnection * con)1619 EIB_MC_GetPEIType_async (EIBConnection * con)
1620 {
1621 uchar head[2];
1622 if (!con)
1623 {
1624 errno = EINVAL;
1625 return -1;
1626 }
1627 EIBSETTYPE (head, EIB_MC_PEI_TYPE);
1628 if (SendRequest (con, 2, head) == -1)
1629 return -1;
1630 con->complete = MC_GetPEIType_complete;
1631 return 0;
1632 }
1633
1634 int
EIB_MC_GetPEIType(EIBConnection * con)1635 EIB_MC_GetPEIType (EIBConnection * con)
1636 {
1637 if (EIB_MC_GetPEIType_async (con) == -1)
1638 return -1;
1639 return EIBComplete (con);
1640 }
1641
1642 static int
MC_ReadADC_complete(EIBConnection * con)1643 MC_ReadADC_complete (EIBConnection * con)
1644 {
1645 int i;
1646 i = GetRequest (con);
1647 if (i == -1)
1648 return -1;
1649 if (EIBTYPE (con) != EIB_MC_ADC_READ || con->size < 4)
1650 {
1651 errno = ECONNRESET;
1652 return -1;
1653 }
1654 if (con->req.ptr1)
1655 *con->req.ptr1 = (con->buf[2] << 8) | (con->buf[3]);
1656 return 0;
1657 }
1658
1659 int
EIB_MC_ReadADC_async(EIBConnection * con,uint8_t channel,uint8_t count,int16_t * val)1660 EIB_MC_ReadADC_async (EIBConnection * con, uint8_t channel, uint8_t count,
1661 int16_t * val)
1662 {
1663 uchar head[4];
1664 if (!con)
1665 {
1666 errno = EINVAL;
1667 return -1;
1668 }
1669 con->req.ptr1 = val;
1670 EIBSETTYPE (head, EIB_MC_ADC_READ);
1671 head[2] = channel;
1672 head[3] = count;
1673 if (SendRequest (con, 4, head) == -1)
1674 return -1;
1675 con->complete = MC_ReadADC_complete;
1676 return 0;
1677 }
1678
1679 int
EIB_MC_ReadADC(EIBConnection * con,uint8_t channel,uint8_t count,int16_t * val)1680 EIB_MC_ReadADC (EIBConnection * con, uint8_t channel, uint8_t count,
1681 int16_t * val)
1682 {
1683 if (EIB_MC_ReadADC_async (con, channel, count, val) == -1)
1684 return -1;
1685 return EIBComplete (con);
1686 }
1687
1688 static int
MC_PropertyRead_complete(EIBConnection * con)1689 MC_PropertyRead_complete (EIBConnection * con)
1690 {
1691 int i;
1692 i = GetRequest (con);
1693 if (i == -1)
1694 return -1;
1695 if (EIBTYPE (con) != EIB_MC_PROP_READ)
1696 {
1697 errno = ECONNRESET;
1698 return -1;
1699 }
1700 i = con->size - 2;
1701 if (i > con->req.len)
1702 i = con->req.len;
1703 memcpy (con->req.buf, con->buf + 2, i);
1704 return i;
1705 }
1706
1707 int
EIB_MC_PropertyRead_async(EIBConnection * con,uint8_t obj,uint8_t property,uint16_t start,uint8_t nr_of_elem,int max_len,uint8_t * buf)1708 EIB_MC_PropertyRead_async (EIBConnection * con, uint8_t obj, uint8_t property,
1709 uint16_t start, uint8_t nr_of_elem, int max_len,
1710 uint8_t * buf)
1711 {
1712 uchar head[7];
1713 if (!con)
1714 {
1715 errno = EINVAL;
1716 return -1;
1717 }
1718 con->req.buf = buf;
1719 con->req.len = max_len;
1720 if (!buf)
1721 {
1722 errno = EINVAL;
1723 return -1;
1724 }
1725 EIBSETTYPE (head, EIB_MC_PROP_READ);
1726 head[2] = obj;
1727 head[3] = property;
1728 head[4] = (start >> 8) & 0xff;
1729 head[5] = (start) & 0xff;
1730 head[6] = nr_of_elem;
1731 if (SendRequest (con, 7, head) == -1)
1732 return -1;
1733 con->complete = MC_PropertyRead_complete;
1734 return 0;
1735 }
1736
1737 int
EIB_MC_PropertyRead(EIBConnection * con,uint8_t obj,uint8_t property,uint16_t start,uint8_t nr_of_elem,int max_len,uint8_t * buf)1738 EIB_MC_PropertyRead (EIBConnection * con, uint8_t obj, uint8_t property,
1739 uint16_t start, uint8_t nr_of_elem, int max_len,
1740 uint8_t * buf)
1741 {
1742 if (EIB_MC_PropertyRead_async
1743 (con, obj, property, start, nr_of_elem, max_len, buf) == -1)
1744 return -1;
1745 return EIBComplete (con);
1746 }
1747
1748 static int
MC_Read_complete(EIBConnection * con)1749 MC_Read_complete (EIBConnection * con)
1750 {
1751 int i;
1752 i = GetRequest (con);
1753 if (i == -1)
1754 return -1;
1755 if (EIBTYPE (con) != EIB_MC_READ)
1756 {
1757 errno = ECONNRESET;
1758 return -1;
1759 }
1760 i = con->size - 2;
1761 if (i > con->req.len)
1762 i = con->req.len;
1763 memcpy (con->req.buf, con->buf + 2, i);
1764 return i;
1765 }
1766
1767 int
EIB_MC_Read_async(EIBConnection * con,uint16_t addr,int len,uint8_t * buf)1768 EIB_MC_Read_async (EIBConnection * con, uint16_t addr, int len, uint8_t * buf)
1769 {
1770 uchar head[6];
1771 if (!con)
1772 {
1773 errno = EINVAL;
1774 return -1;
1775 }
1776 if (!buf)
1777 {
1778 errno = EINVAL;
1779 return -1;
1780 }
1781 con->req.len = len;
1782 con->req.buf = buf;
1783 EIBSETTYPE (head, EIB_MC_READ);
1784 head[2] = (addr >> 8) & 0xff;
1785 head[3] = (addr) & 0xff;
1786 head[4] = (len >> 8) & 0xff;
1787 head[5] = (len) & 0xff;
1788 if (SendRequest (con, 6, head) == -1)
1789 return -1;
1790 con->complete = MC_Read_complete;
1791 return 0;
1792 }
1793
1794 int
EIB_MC_Read(EIBConnection * con,uint16_t addr,int len,uint8_t * buf)1795 EIB_MC_Read (EIBConnection * con, uint16_t addr, int len, uint8_t * buf)
1796 {
1797 if (EIB_MC_Read_async (con, addr, len, buf) == -1)
1798 return -1;
1799 return EIBComplete (con);
1800 }
1801
1802 static int
MC_PropertyWrite_complete(EIBConnection * con)1803 MC_PropertyWrite_complete (EIBConnection * con)
1804 {
1805 int i;
1806 i = GetRequest (con);
1807 if (i == -1)
1808 return -1;
1809 if (EIBTYPE (con) != EIB_MC_PROP_WRITE)
1810 {
1811 errno = ECONNRESET;
1812 return -1;
1813 }
1814 i = con->size - 2;
1815 if (i > con->req.len)
1816 i = con->req.len;
1817 memcpy (con->req.buf, con->buf + 2, i);
1818 return i;
1819 }
1820
1821 int
EIB_MC_PropertyWrite_async(EIBConnection * con,uint8_t obj,uint8_t property,uint16_t start,uint8_t nr_of_elem,int len,const uint8_t * buf,int max_len,uint8_t * res)1822 EIB_MC_PropertyWrite_async (EIBConnection * con, uint8_t obj,
1823 uint8_t property, uint16_t start,
1824 uint8_t nr_of_elem, int len, const uint8_t * buf,
1825 int max_len, uint8_t * res)
1826 {
1827 uchar *ibuf;
1828 int i;
1829 if (!con)
1830 {
1831 errno = EINVAL;
1832 return -1;
1833 }
1834 if (!buf || !res)
1835 {
1836 errno = EINVAL;
1837 return -1;
1838 }
1839 con->req.len = max_len;
1840 con->req.buf = res;
1841 ibuf = (uchar *) malloc (len + 7);
1842 if (!ibuf)
1843 {
1844 errno = ENOMEM;
1845 return -1;
1846 }
1847 EIBSETTYPE (ibuf, EIB_MC_PROP_WRITE);
1848 ibuf[2] = obj;
1849 ibuf[3] = property;
1850 ibuf[4] = (start >> 8) & 0xff;
1851 ibuf[5] = (start) & 0xff;
1852 ibuf[6] = nr_of_elem;
1853 memcpy (ibuf + 7, buf, len);
1854 i = SendRequest (con, len + 7, ibuf);
1855 free (ibuf);
1856 if (i == -1)
1857 return -1;
1858 con->complete = MC_PropertyWrite_complete;
1859 return 0;
1860 }
1861
1862 int
EIB_MC_PropertyWrite(EIBConnection * con,uint8_t obj,uint8_t property,uint16_t start,uint8_t nr_of_elem,int len,const uint8_t * buf,int max_len,uint8_t * res)1863 EIB_MC_PropertyWrite (EIBConnection * con, uint8_t obj, uint8_t property,
1864 uint16_t start, uint8_t nr_of_elem, int len,
1865 const uint8_t * buf, int max_len, uint8_t * res)
1866 {
1867 if (EIB_MC_PropertyWrite_async
1868 (con, obj, property, start, nr_of_elem, len, buf, max_len, res) == -1)
1869 return -1;
1870 return EIBComplete (con);
1871 }
1872 static int
MC_Write_complete(EIBConnection * con)1873 MC_Write_complete (EIBConnection * con)
1874 {
1875 int i;
1876 i = GetRequest (con);
1877 if (i == -1)
1878 return -1;
1879 if (EIBTYPE (con) == EIB_ERROR_VERIFY)
1880 {
1881 errno = EIO;
1882 return -1;
1883 }
1884 if (EIBTYPE (con) != EIB_MC_WRITE)
1885 {
1886 errno = ECONNRESET;
1887 return -1;
1888 }
1889 return con->req.len;
1890 }
1891
1892 int
EIB_MC_Write_async(EIBConnection * con,uint16_t addr,int len,const uint8_t * buf)1893 EIB_MC_Write_async (EIBConnection * con, uint16_t addr, int len,
1894 const uint8_t * buf)
1895 {
1896 uchar *ibuf;
1897 int i;
1898 if (!con)
1899 {
1900 errno = EINVAL;
1901 return -1;
1902 }
1903 con->req.len = len;
1904 if (!buf)
1905 {
1906 errno = EINVAL;
1907 return -1;
1908 }
1909 ibuf = (uchar *) malloc (len + 6);
1910 if (!ibuf)
1911 {
1912 errno = ENOMEM;
1913 return -1;
1914 }
1915 EIBSETTYPE (ibuf, EIB_MC_WRITE);
1916 ibuf[2] = (addr >> 8) & 0xff;
1917 ibuf[3] = (addr) & 0xff;
1918 ibuf[4] = (len >> 8) & 0xff;
1919 ibuf[5] = (len) & 0xff;
1920 memcpy (ibuf + 6, buf, len);
1921 i = SendRequest (con, len + 6, ibuf);
1922 free (ibuf);
1923 if (i == -1)
1924 return -1;
1925 con->complete = MC_Write_complete;
1926 return 0;
1927 }
1928
1929 int
EIB_MC_Write(EIBConnection * con,uint16_t addr,int len,const uint8_t * buf)1930 EIB_MC_Write (EIBConnection * con, uint16_t addr, int len,
1931 const uint8_t * buf)
1932 {
1933 if (EIB_MC_Write_async (con, addr, len, buf) == -1)
1934 return -1;
1935 return EIBComplete (con);
1936 }
1937
1938 static int
MC_PropertyDesc_complete(EIBConnection * con)1939 MC_PropertyDesc_complete (EIBConnection * con)
1940 {
1941 int i;
1942 i = GetRequest (con);
1943 if (i == -1)
1944 return -1;
1945 if (EIBTYPE (con) != EIB_MC_PROP_DESC || con->size < 6)
1946 {
1947 errno = ECONNRESET;
1948 return -1;
1949 }
1950 /* Type */
1951 if (con->req.ptr2)
1952 *con->req.ptr2 = con->buf[2];
1953 /* max_nr_of_elem */
1954 if (con->req.ptr4)
1955 *con->req.ptr4 = (con->buf[3] << 8) | (con->buf[4]);
1956 /* access */
1957 if (con->req.ptr3)
1958 *con->req.ptr3 = con->buf[5];
1959 return 0;
1960 }
1961
1962 int
EIB_MC_PropertyDesc_async(EIBConnection * con,uint8_t obj,uint8_t property,uint8_t * type,uint16_t * max_nr_of_elem,uint8_t * access)1963 EIB_MC_PropertyDesc_async (EIBConnection * con, uint8_t obj, uint8_t property,
1964 uint8_t * type, uint16_t * max_nr_of_elem,
1965 uint8_t * access)
1966 {
1967 uchar head[5];
1968 if (!con)
1969 {
1970 errno = EINVAL;
1971 return -1;
1972 }
1973 con->req.ptr2 = type;
1974 con->req.ptr4 = max_nr_of_elem;
1975 con->req.ptr3 = access;
1976 EIBSETTYPE (head, EIB_MC_PROP_DESC);
1977 head[2] = obj;
1978 head[3] = property;
1979 if (SendRequest (con, 4, head) == -1)
1980 return -1;
1981 con->complete = MC_PropertyDesc_complete;
1982 return 0;
1983 }
1984
1985 int
EIB_MC_PropertyDesc(EIBConnection * con,uint8_t obj,uint8_t property,uint8_t * type,uint16_t * max_nr_of_elem,uint8_t * access)1986 EIB_MC_PropertyDesc (EIBConnection * con, uint8_t obj, uint8_t property,
1987 uint8_t * type, uint16_t * max_nr_of_elem,
1988 uint8_t * access)
1989 {
1990 if (EIB_MC_PropertyDesc_async
1991 (con, obj, property, type, max_nr_of_elem, access) == -1)
1992 return -1;
1993 return EIBComplete (con);
1994 }
1995
1996 static int
MC_Authorize_complete(EIBConnection * con)1997 MC_Authorize_complete (EIBConnection * con)
1998 {
1999 int i;
2000 i = GetRequest (con);
2001 if (i == -1)
2002 return -1;
2003 if (EIBTYPE (con) != EIB_MC_AUTHORIZE || con->size < 3)
2004 {
2005 errno = ECONNRESET;
2006 return -1;
2007 }
2008 return con->buf[2];
2009 }
2010
2011 int
EIB_MC_Authorize_async(EIBConnection * con,uint8_t key[4])2012 EIB_MC_Authorize_async (EIBConnection * con, uint8_t key[4])
2013 {
2014 uchar head[6];
2015 if (!con)
2016 {
2017 errno = EINVAL;
2018 return -1;
2019 }
2020 EIBSETTYPE (head, EIB_MC_AUTHORIZE);
2021 memcpy (head + 2, key, 4);
2022 if (SendRequest (con, 6, head) == -1)
2023 return -1;
2024 con->complete = MC_Authorize_complete;
2025 return 0;
2026 }
2027
2028 int
EIB_MC_Authorize(EIBConnection * con,uint8_t key[4])2029 EIB_MC_Authorize (EIBConnection * con, uint8_t key[4])
2030 {
2031 if (EIB_MC_Authorize_async (con, key) == -1)
2032 return -1;
2033 return EIBComplete (con);
2034 }
2035
2036 static int
MC_SetKey_complete(EIBConnection * con)2037 MC_SetKey_complete (EIBConnection * con)
2038 {
2039 int i;
2040 i = GetRequest (con);
2041 if (i == -1)
2042 return -1;
2043 if (EIBTYPE (con) == EIB_PROCESSING_ERROR)
2044 {
2045 errno = EPERM;
2046 return -1;
2047 }
2048 if (EIBTYPE (con) != EIB_MC_KEY_WRITE)
2049 {
2050 errno = ECONNRESET;
2051 return -1;
2052 }
2053 return 0;
2054 }
2055
2056 int
EIB_MC_SetKey_async(EIBConnection * con,uint8_t key[4],uint8_t level)2057 EIB_MC_SetKey_async (EIBConnection * con, uint8_t key[4], uint8_t level)
2058 {
2059 uchar head[7];
2060 if (!con)
2061 {
2062 errno = EINVAL;
2063 return -1;
2064 }
2065 EIBSETTYPE (head, EIB_MC_KEY_WRITE);
2066 memcpy (head + 2, key, 4);
2067 head[6] = level;
2068 if (SendRequest (con, 7, head) == -1)
2069 return -1;
2070 con->complete = MC_SetKey_complete;
2071 return 0;
2072 }
2073
2074 int
EIB_MC_SetKey(EIBConnection * con,uint8_t key[4],uint8_t level)2075 EIB_MC_SetKey (EIBConnection * con, uint8_t key[4], uint8_t level)
2076 {
2077 if (EIB_MC_SetKey_async (con, key, level) == -1)
2078 return -1;
2079 return EIBComplete (con);
2080 }
2081
2082 static int
MC_PropertyScan_complete(EIBConnection * con)2083 MC_PropertyScan_complete (EIBConnection * con)
2084 {
2085 int i;
2086 i = GetRequest (con);
2087 if (i == -1)
2088 return -1;
2089 if (EIBTYPE (con) != EIB_MC_PROP_SCAN)
2090 {
2091 errno = ECONNRESET;
2092 return -1;
2093 }
2094 i = con->size - 2;
2095 if (i > con->req.len)
2096 i = con->req.len;
2097 memcpy (con->req.buf, con->buf + 2, i);
2098 return i;
2099 }
2100
2101 int
EIB_MC_PropertyScan_async(EIBConnection * con,int maxlen,uint8_t * buf)2102 EIB_MC_PropertyScan_async (EIBConnection * con, int maxlen, uint8_t * buf)
2103 {
2104 uchar head[2];
2105 if (!con)
2106 {
2107 errno = EINVAL;
2108 return -1;
2109 }
2110 con->req.len = maxlen;
2111 con->req.buf = buf;
2112 EIBSETTYPE (head, EIB_MC_PROP_SCAN);
2113 if (SendRequest (con, 2, head) == -1)
2114 return -1;
2115 con->complete = MC_PropertyScan_complete;
2116 return 0;
2117 }
2118
2119 int
EIB_MC_PropertyScan(EIBConnection * con,int maxlen,uint8_t * buf)2120 EIB_MC_PropertyScan (EIBConnection * con, int maxlen, uint8_t * buf)
2121 {
2122 if (EIB_MC_PropertyScan_async (con, maxlen, buf) == -1)
2123 return -1;
2124 return EIBComplete (con);
2125 }
2126
2127 static int
LoadImage_complete(EIBConnection * con)2128 LoadImage_complete (EIBConnection * con)
2129 {
2130 int i;
2131 i = GetRequest (con);
2132 if (i == -1)
2133 return -1;
2134 if (EIBTYPE (con) != EIB_LOAD_IMAGE || con->size < 4)
2135 {
2136 errno = ECONNRESET;
2137 return IMG_UNKNOWN_ERROR;
2138 }
2139 return (con->buf[2] << 8) | con->buf[3];
2140 }
2141
2142 int
EIB_LoadImage_async(EIBConnection * con,const uint8_t * image,int len)2143 EIB_LoadImage_async (EIBConnection * con, const uint8_t * image, int len)
2144 {
2145 uchar *ibuf;
2146 int i;
2147 if (!con)
2148 {
2149 errno = EINVAL;
2150 return -1;
2151 }
2152 if (!image)
2153 {
2154 errno = EINVAL;
2155 return -1;
2156 }
2157 ibuf = (uchar *) malloc (len + 2);
2158 if (!ibuf)
2159 {
2160 errno = ENOMEM;
2161 return -1;
2162 }
2163 EIBSETTYPE (ibuf, EIB_LOAD_IMAGE);
2164 memcpy (ibuf + 2, image, len);
2165 i = SendRequest (con, len + 2, ibuf);
2166 free (ibuf);
2167 if (i == -1)
2168 return -1;
2169 con->complete = LoadImage_complete;
2170 return 0;
2171 }
2172
2173 BCU_LOAD_RESULT
EIB_LoadImage(EIBConnection * con,const uint8_t * image,int len)2174 EIB_LoadImage (EIBConnection * con, const uint8_t * image, int len)
2175 {
2176 if (EIB_LoadImage_async (con, image, len) == -1)
2177 return -1;
2178 return EIBComplete (con);
2179 }
2180