ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/truck/DashInterface/Display.cpp
(Generate patch)

Comparing DashInterface/Display.cpp (file contents):
Revision 32 by douglas, 2008-02-29T12:47:34-08:00 vs.
Revision 38 by douglas, 2008-03-05T13:36:38-08:00

# Line 5 | Line 5
5   // $Id$
6  
7   #include <foreach.hpp>
8 + #include <scopes.hpp>
9 + #include <timing.hpp>
10  
11   #include <iomanip>
12   #include <iostream>
# Line 72 | Line 74 | Display::Packet::Packet(Display::Packet:
74  
75   std::ostream &operator<<(std::ostream &output, const Display::Packet &packet)
76   {
77 <        return output << _B("0x") << std::hex << std::setw(2) << std::setfill('0') << unsigned(packet.command) << std::dec << std::setw(0) << std::setfill(' ') << _B(" [") << packet.GetData() << ']';
77 >        return output << _B("0x") << std::hex << std::setw(2) << std::setfill('0') << unsigned(packet.command) << _B(" [") << packet.GetData() << ']';
78   }
79  
80   void operator<<(int fd, const Display::Packet &packet)
# Line 98 | Line 100 | void operator>>(int fd, Display::Packet
100  
101   void Communicate(Display *display)
102   {
103 <        while (true)
102 <                std::cout << _B("Hello!") << std::endl;
103 >        display->Communicate_();
104   }
105  
106 < Display::Display(const std::string &device) : ucom(Posix::Open(device, O_RDWR | O_NOCTTY)), thread(reinterpret_cast<void *(*)(void *)>(::Communicate), this)
106 > void Activity(Display *display)
107 > {
108 >        display->Activity();
109 > }
110 >
111 > Display::Display(const std::string &device, Callback callback) : ucom(Posix::Open(device, O_RDWR | O_NOCTTY | O_NONBLOCK)), ucomCondition(ucomLock), running(true), responsesCondition(responsesLock), keyActivityCondition(keyActivityLock), callback(callback), communicate(reinterpret_cast<void *(*)(void *)>(::Communicate), this), activity(reinterpret_cast<void *(*)(void *)>(::Activity), this)
112   {
113          ::termios state;
114  
# Line 119 | Line 125 | Display::Display(const std::string &devi
125          state.c_lflag |= NOFLSH;
126  
127          Posix::CheckError(::tcsetattr(ucom, TCSANOW, &state));
128 +
129 +        _synchronized (ucomLock)
130 +                ucomCondition.Signal();
131 + }
132 +
133 + Display::~Display()
134 + {
135 +        running = false;
136 +
137 +        communicate.Join();
138 +        activity.Join();
139 +
140 +        Posix::Close(ucom);
141 + }
142 +
143 + void Display::Communicate_()
144 + {
145 +        _synchronized (ucomLock)
146 +                ucomCondition.Wait();
147 +
148 +        while (running)
149 +        {
150 +                Packet response;
151 +
152 +                _synchronized (ucomLock)
153 +                        try
154 +                        {
155 +                                ucom >> response;
156 +                        }
157 +                        catch (const Posix::Error error)
158 +                        {
159 +                                if (error.what() != _B("Resource temporarily unavailable"))
160 +                                        throw error;
161 +
162 +                                goto next;
163 +                        }
164 +
165 +                if ((response.command & Packet::Error) == Packet::Error);
166 +                else if ((response.command & Packet::Report) == Packet::Report)
167 +                        switch (response.command)
168 +                        {
169 +                        case Packet::KeyActivity:
170 +                                _synchronized (keyActivityLock)
171 +                                {
172 +                                        keyActivity.push(response);
173 +                                        keyActivityCondition.Signal();
174 +                                }
175 +
176 +                                break;
177 +                        case Packet::FanSpeedReport:
178 +                        case Packet::TemperatureSensorReport:
179 +                                break;
180 +                        }
181 +                else if ((response.command & Packet::Response) == Packet::Response)
182 +                        _synchronized (responsesLock)
183 +                        {
184 +                                responses.push(response);
185 +                                responsesCondition.Signal();
186 +                        }
187 +
188 + next:   Timing::NanoSleep(Timing::Time(0, 10000000));
189 +        }
190 +
191 +        keyActivityCondition.Signal();
192   }
193  
194   Display::Packet Display::Communicate_(Display::Packet::Command command, uint8_t length, const uint8_t *data)
195   {
196 <        Packet packet(command, length, data), response;
196 >        Packet packet(command, length, data);
197  
198 <        ucom << packet;
198 > retry:
199 >        _synchronized (ucomLock)
200 >                ucom << packet;
201  
202 <        _forever
202 >        _synchronized (responsesLock)
203          {
204 <                ucom >> response;
204 >                while (responses.empty())
205 >                        try
206 >                        {
207 >                                responsesCondition.Wait(Timing::GetTimeOfDay() += 1);
208 >                        }
209 >                        catch (const Posix::Error &error)
210 >                        {
211 >                                if (error.what() != _B("Operation timed out"))
212 >                                        throw error;
213 >
214 >                                goto retry;
215 >                        }
216  
217 <                if (packet.command | Packet::Response == response.command)
135 <                        return response;
217 >                Packet response(responses.front());
218  
219 <                switch (response.command)
219 >                responses.pop();
220 >
221 >                assert ((packet.command | Packet::Response) == response.command);
222 >
223 >                return response;
224 >        }
225 >
226 >        throw;
227 > }
228 >
229 > void Display::Activity()
230 > {
231 >        if (callback == NULL)
232 >                return;
233 >
234 >        while (running)
235 >                _synchronized (keyActivityLock)
236                  {
237 <                case Packet::KeyActivity:
238 <                        keyActivity.push(response);
237 >                        while (keyActivity.empty())
238 >                                keyActivityCondition.Wait();
239  
240 <                        break;
241 <                case Packet::FanSpeedReport:
242 <                case Packet::TemperatureSensorReport:
243 <                        break;
240 >                        while (keyActivity.size())
241 >                        {
242 >                                KeyActivity activity(KeyActivity(*keyActivity.front().data));
243 >
244 >                                keyActivity.pop();
245 >
246 >                                _desynchronized (keyActivityLock)
247 >                                        callback(activity);
248 >                        }
249                  }
147        }
250   }
251  
252   bool Display::Ping(const std::string &data)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines