]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/simpad-utilities/serload/serialdownload.cpp
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / simpad-utilities / serload / serialdownload.cpp
1 //=============================================================================
2 // Project:      SIMpad
3 //=============================================================================
4 // FILE-NAME:    serialdownload.cpp
5 // FUNCTION:     Serial download of a new image from PC to SIMpad
6 //
7 // AUTHOR:       Juergen Messerer, Peter Voser
8 // CREAT.-DATE:  01.04.2001 (dd.mm.yy)
9 //
10 // NOTES:        -
11 //
12 //=============================================================================
13
14 #include <iostream>
15 #include "serialdownload.h"
16 using namespace std;
17
18 //=============================================================================
19 //=============================================================================
20 SerialDownload::SerialDownload()
21 {
22 }
23
24 //=============================================================================
25 //=============================================================================
26 SerialDownload::~SerialDownload()
27 {
28 }
29
30 //=============================================================================
31 //=============================================================================
32 int SerialDownload::openSerialPort(const char* portDev, int& errorNumber)
33 {
34     _serialPort = open(portDev, O_RDWR | O_NONBLOCK);
35
36     if (_serialPort == -1)
37     {
38         errorNumber = errno;
39         return -1;
40     }
41
42     // Read old serial port setup
43     termios serialPortSetup;
44     int success = tcgetattr(_serialPort, &serialPortSetup );     
45     if (success < 0) 
46     {
47         errorNumber = errno;
48         perror(0);
49         return -1;
50     }
51
52     serialPortSetup.c_iflag = 0L;
53     serialPortSetup.c_oflag = 0L;
54
55     // Control mode flags
56     serialPortSetup.c_cflag &= ~(CSTOPB|PARENB|CRTSCTS);
57     serialPortSetup.c_cflag |= (CS8|CLOCAL);
58
59     // Local mode flags
60     serialPortSetup.c_lflag = 0L;
61
62     // control characters
63     serialPortSetup.c_cc[VTIME] = 0;
64     serialPortSetup.c_cc[VMIN] = 0;
65
66     // Set baud rate = 38.4kBaud
67     cfsetispeed(&serialPortSetup, B38400);
68     cfsetospeed(&serialPortSetup, B38400);
69
70     success=tcsetattr(_serialPort, TCSANOW, &serialPortSetup);
71     if(success < 0)
72     {
73         errorNumber = errno;
74         perror(0);
75         return -1;
76     }
77
78     return 0;
79 }
80
81 //=============================================================================
82 //=============================================================================
83 int SerialDownload::loadFile(const char *fileName, 
84                              char *&buffer, 
85                              int &numberOfBytes)
86 {
87     FILE *path;
88
89     if((path = fopen(fileName,"rb")) == 0)
90     {
91         // Specified file not found.
92         return -1;
93     }
94
95     fseek(path, 0, 2);
96     numberOfBytes = ftell(path);
97     rewind(path);
98
99     buffer = (char*)malloc((size_t)numberOfBytes);
100     if(buffer == 0)
101     {
102         // Insufficient memory to load file.
103         fclose(path);
104         return -2;
105     }
106
107     if(fread(buffer, numberOfBytes, 1, path) != 1)
108     {
109         // Cannot read file.
110         fclose(path);
111         return -3;
112     }
113
114     fclose(path);
115     return 0;
116 }
117
118 //=============================================================================
119 //=============================================================================
120 bool SerialDownload::changeBaudRate(const int newBaudRate, 
121                                     int& errorNumber)
122 {
123     int success;
124     int baudRate;
125     struct termios setup;
126
127     switch(newBaudRate)
128     {
129     case 9600:
130         baudRate = B9600;
131         break;
132     case 19200:
133         baudRate = B19200;
134         break;
135     case 38400:
136         baudRate = B38400;
137         break;
138     case 57600:
139         baudRate = B57600;
140         break;
141     case 115200:
142         baudRate = B115200;
143         break;
144     case 230400:
145         baudRate = B230400;
146         break;
147     case 460800:
148         baudRate = B460800;
149         break;
150     default:
151         return 0;
152         break;
153     }
154
155     success = tcgetattr(_serialPort, &setup);
156     if (success < 0)
157     {
158         errorNumber = errno;
159         perror(0);
160         return 0;
161     }
162
163     cfsetispeed(&setup, baudRate);
164     cfsetospeed(&setup, baudRate);
165     success = tcsetattr(_serialPort, TCSANOW, &setup);
166     if (success < 0) 
167     {
168         errorNumber = errno;
169         perror(0);
170         return 0;
171     }
172
173     return 1;
174 }
175
176 //=============================================================================
177 //=============================================================================
178 unsigned char SerialDownload::waitForReply(const int transparent)
179 {
180     unsigned char c(0);
181     int numberBytes(0);
182     int reply(0);
183
184     struct pollfd commEvent;
185     commEvent.fd = _serialPort;
186     commEvent.events = POLLIN;
187
188     for(;;)
189     {
190         // Wait until a character has received.
191         do
192         {
193             reply = poll(&commEvent, 1, 1000);
194         }
195         while(reply == 0);
196
197         if(commEvent.revents == POLLIN)
198         {
199             do
200             {
201                 numberBytes=read(_serialPort, &c, 1);
202                 if(transparent && numberBytes)
203                 {
204                     cout << c;
205                     cout.flush();
206                 }
207                 if((c == STX) || 
208                    (c == ETX) || 
209                    (c == BEL) || 
210                    (c == ACK_OK) || 
211                    (c == ACK_NOK))
212                 {
213                     return c;
214                 }
215             }
216             while(numberBytes);
217         }
218     }
219     return 0;
220 }
221
222 //=============================================================================
223 //=============================================================================
224 int SerialDownload::connectToSimpad(const int fastBaudRate, 
225                                     int& errorNumber)
226 {
227     errorNumber = 0;
228     int bytesWritten;
229     unsigned char c;
230
231     // Switch baud rate to low connecting baud rate.
232     if(!changeBaudRate(38400, errorNumber))
233     {
234         return -1;
235     }
236
237     // Wait for character STX (02) and BEL (07)
238     while(waitForReply(1) != STX);
239     while(waitForReply(1) != BEL);
240     bytesWritten = write(_serialPort, &ACK_BD, 1);
241     if(!bytesWritten)
242     {
243         errorNumber = errno;
244         return -2;
245     }
246
247     // Send byte #2 of baud rate
248     c = (fastBaudRate>>16)&0xff;
249     bytesWritten = write(_serialPort, &c, 1);
250     if(!bytesWritten)
251     {
252         errorNumber = errno;
253         return -2;
254     }
255
256     // Send byte #1 of baud rate
257     c = (fastBaudRate>>8)&0xff;
258     bytesWritten = write(_serialPort, &c, 1);
259     if(!bytesWritten)
260     {
261         errorNumber = errno;
262         return -2;
263     }
264
265     // Send byte #0 of baud rate
266     c = fastBaudRate&0xff;
267     bytesWritten = write(_serialPort, &c, 1);
268     if(!bytesWritten)
269     {
270         errorNumber = errno;
271         return -2;
272     }
273
274     c = waitForReply(1);
275     if (c == ACK_OK)
276     {
277         // Switch baud rate to fast baud rate.
278         if(!changeBaudRate(fastBaudRate, errorNumber))
279         {
280             return -3;
281         }
282     }
283
284     // Wait for 1st character with new baud rate.
285     while(waitForReply(1) != STX);
286
287     bytesWritten = write(_serialPort, &STX, 1);
288     if(!bytesWritten)
289     {
290         errorNumber = errno;
291         return -4;
292     }
293
294     while(waitForReply(1) != STX);
295     return 0;
296 }
297
298 //=============================================================================
299 //=============================================================================
300 bool SerialDownload::sendBlock(const char *buffer, 
301                                const int length, 
302                                int& errorNumber)
303 {
304     errorNumber = 0;
305     unsigned char c, check=0xff;
306     int i;
307     int bytesWritten;
308
309     while(1)
310     {
311         if(length == 512)
312         {
313             // It's a complete block.
314             bytesWritten = write(_serialPort, buffer, 512);
315             if(!bytesWritten)
316             {
317                 errorNumber = errno;
318                 return 0;
319             }
320             // Create checksum.
321             for(i = 0; i < 512; ++i)
322             {
323                 check=(check<<1) ^ buffer[i];
324             }
325         }
326         else
327         {
328             // It's an incomplete block, which must be filled with 
329             // the FILLER pattern. 
330             char lastBlock[512];
331             for(i = 0; i < 512; ++i)
332             {
333                 if(i < length)
334                 {
335                     // Create checksum.
336                     check=(check<<1) ^ buffer[i];
337                     lastBlock[i] = buffer[i];
338                 }
339                 else
340                 {
341                     // Create checksum
342                     check=(check<<1) ^ FILLER;
343                     lastBlock[i] = FILLER;
344                 }
345             }
346             bytesWritten = write(_serialPort, lastBlock, 512);
347             if(!bytesWritten)
348             {
349                 errorNumber = errno;
350                 return 0;
351             }
352         }
353
354         while(waitForReply(1) != STX);
355
356         if(length == 512)
357         {
358             bytesWritten = write(_serialPort, &STX, 1);
359             if(!bytesWritten)
360             {
361                 errorNumber = errno;
362                 return 0;
363             }
364         }
365         else
366         {
367             // It was the last block.
368             bytesWritten = write(_serialPort, &ETX, 1);
369             if(!bytesWritten)
370             {
371                 errorNumber = errno;
372                 return 0;
373             }
374         }
375
376         // Send checksum. 
377         bytesWritten = write(_serialPort, &check, 1);
378         if(!bytesWritten)
379         {
380             errorNumber = errno;
381             return 0;
382         }
383
384         // Wait for ACK_OK as confirmation. Send block again otherwise. 
385         c = waitForReply(1);
386         if(c == ACK_OK)
387         {
388             // The block was successfully sent.
389             return 1;
390         }
391     }
392 }
393
394 //=============================================================================
395 //=============================================================================
396 void SerialDownload::waitForEndOfBurning(void)
397 {
398     // Wait for ETX, which indicates the end of burning.
399     while(waitForReply(1) != ETX);
400
401     // Send the characters "r" (erase registry) and "o" (power off).
402     char c = 'r';
403     int bytesWritten;
404     bytesWritten = write(_serialPort, &c, 1);
405     c = 'o';
406     bytesWritten = write(_serialPort, &c, 1);
407     usleep(7000);
408 }