]> git.tdb.fi Git - r2c2.git/blob - source/libmarklin/reply.cpp
Forgot to add the new files
[r2c2.git] / source / libmarklin / reply.cpp
1 /* $Id$
2
3 This file is part of the MSP Märklin suite
4 Copyright © 2006-2009  Mikkosoft Productions, Mikko Rasa
5 Distributed under the GPL
6 */
7
8 #include <cstring>
9 #include <unistd.h>
10 #include <msp/strings/formatter.h>
11 #include "constants.h"
12 #include "reply.h"
13
14 using namespace std;
15 using namespace Msp;
16
17 namespace {
18
19 unsigned read_all(int fd, char *buf, unsigned size)
20 {
21         unsigned pos = 0;
22         while(pos<size)
23                 pos += read(fd, buf+pos, size-pos);
24
25         return pos;
26 }
27
28 }
29
30 namespace Marklin {
31
32 Reply::Reply():
33         err(ERR_NO_ERROR),
34         len(0)
35 {
36         memset(data, 0, 128);
37 }
38
39 Reply Reply::read(int fd, Cmd cmd)
40 {
41         Reply result;
42
43         char *data = reinterpret_cast<char *>(result.data);
44
45         if(cmd==CMD_EVENT)
46         {
47                 for(unsigned i=0; i<3; ++i)
48                 {
49                         result.len += read_all(fd, data+i, 1);
50                         if(!(result.data[i]&0x80))
51                                 break;
52                 }
53         }
54         else if(cmd==CMD_EVENT_LOK)
55         {
56                 for(unsigned i=0;; i+=5)
57                 {
58                         result.len += read_all(fd, data+i, 1);
59
60                         if(result.data[i]&0x80)
61                                 break;
62
63                         result.len += read_all(fd, data+i+1, 4);
64                 }
65         }
66         else if(cmd==CMD_EVENT_TURNOUT)
67         {
68                 result.len += read_all(fd, data, 1);
69                 result.len += read_all(fd, data+1, result.data[0]*2);
70         }
71         else if(cmd==CMD_EVENT_SENSOR)
72         {
73                 for(unsigned i=0;; i+=3)
74                 {
75                         result.len += read_all(fd, data+i, 1);
76
77                         if(result.data[i]==0)
78                                 break;
79
80                         result.len += read_all(fd, data+i+1, 2);
81                 }
82         }
83         else
84         {
85                 bool expect_errcode = (cmd!=CMD_STATUS);
86
87                 unsigned expected_bytes = 0;
88                 if(cmd==CMD_STATUS || cmd==CMD_FUNC_STATUS || cmd==CMD_TURNOUT_STATUS)
89                         expected_bytes = 1;
90                 if(cmd==CMD_SENSOR_STATUS || cmd==CMD_TURNOUT_GROUP_STATUS)
91                         expected_bytes = 2;
92                 if(cmd==CMD_LOK_STATUS)
93                         expected_bytes = 3;
94                 if(cmd==CMD_LOK_CONFIG)
95                         expected_bytes = 4;
96
97                 if(expect_errcode)
98                 {
99                         char c;
100                         read_all(fd, &c, 1);
101                         result.err = static_cast<Error>(c);
102                 }
103
104                 if(result.err==ERR_NO_ERROR)
105                         result.len += read_all(fd, data, expected_bytes);
106         }
107
108         return result;
109 }
110
111 Reply Reply::simulate(Cmd cmd)
112 {
113         Reply result;
114
115         if(cmd==CMD_STATUS)
116         {
117                 result.data[0] = 0x80;
118                 result.len = 1;
119         }
120         if(cmd==CMD_EVENT)
121                 result.len = 1;
122         else if(cmd==CMD_TURNOUT)
123                 ;
124         else if(cmd==CMD_TURNOUT_STATUS)
125         {
126                 result.data[0] = 0x04;
127                 result.len = 1;
128         }
129         else if(cmd==CMD_LOK)
130                 ;
131         else if(cmd==CMD_LOK_STATUS)
132         {
133                 result.data[1] = 0x20;
134                 result.len = 3;
135         }
136         else if(cmd==CMD_SENSOR_PARAM_SET)
137                 ;
138         else if(cmd==CMD_SENSOR_REPORT)
139                 ;
140         else if(cmd==CMD_POWER_ON)
141                 ;
142         else if(cmd==CMD_POWER_OFF)
143                 ;
144         else
145                 result.err = ERR_SYS_ERROR;
146
147         return result;
148 }
149
150 ostream &operator<<(ostream &out, const Reply &reply)
151 {
152         out<<reply.err;
153         for(unsigned i=0; i<reply.len; ++i)
154                 out<<format(" %02X", static_cast<int>(reply.data[i]));
155
156         return out;
157 }
158
159 } // namespace Marklin