diff options
author | Daniel Stenberg <daniel@haxx.se> | 2003-07-21 10:56:23 +0000 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2003-07-21 10:56:23 +0000 |
commit | 754426e11f82eca75bbca302674d4cc92cdf53be (patch) | |
tree | 9a1e374332b68348e9d29842448ba6c2c2067592 /apps/plugins/rockbox_flash.c | |
parent | bf6481e79d2eef90183cdd07ada7633fdc5fcf55 (diff) | |
download | rockbox-754426e11f82eca75bbca302674d4cc92cdf53be.tar.gz rockbox-754426e11f82eca75bbca302674d4cc92cdf53be.zip |
Massive code-policing. Use proper indent. Use proper comments. Use proper
source code width.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3857 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/rockbox_flash.c')
-rw-r--r-- | apps/plugins/rockbox_flash.c | 1052 |
1 files changed, 537 insertions, 515 deletions
diff --git a/apps/plugins/rockbox_flash.c b/apps/plugins/rockbox_flash.c index 9a8306e5df..1fb8ce5bcc 100644 --- a/apps/plugins/rockbox_flash.c +++ b/apps/plugins/rockbox_flash.c | |||
@@ -35,398 +35,415 @@ | |||
35 | #define UINT32 unsigned long | 35 | #define UINT32 unsigned long |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | // hard-coded values | 38 | /* hard-coded values */ |
39 | static volatile UINT8* FB = (UINT8*)0x02000000; // Flash base address | 39 | static volatile UINT8* FB = (UINT8*)0x02000000; /* Flash base address */ |
40 | #define SECTORSIZE 4096 // size of one flash sector | 40 | #define SECTORSIZE 4096 /* size of one flash sector */ |
41 | 41 | ||
42 | #define ROCKBOX_DEST 0x09000000 | 42 | #define ROCKBOX_DEST 0x09000000 |
43 | #define ROCKBOX_EXEC 0x09000200 | 43 | #define ROCKBOX_EXEC 0x09000200 |
44 | #define FILENAME "/rockbox.ucl" | 44 | #define FILENAME "/rockbox.ucl" |
45 | #define VERS_ADR 0xFE // position of firmware version value in Flash | 45 | #define VERS_ADR 0xFE /* position of firmware version value in Flash */ |
46 | #define UCL_HEADER 26 // size of the header generated by uclpack | 46 | #define UCL_HEADER 26 /* size of the header generated by uclpack */ |
47 | 47 | ||
48 | typedef struct | 48 | typedef struct |
49 | { | 49 | { |
50 | UINT32 destination; // address to copy it to | 50 | UINT32 destination; /* address to copy it to */ |
51 | UINT32 size; // how many bytes of payload (to the next header) | 51 | UINT32 size; /* how many bytes of payload (to the next header) */ |
52 | UINT32 execute; // entry point | 52 | UINT32 execute; /* entry point */ |
53 | UINT32 flags; // uncompressed or compressed | 53 | UINT32 flags; /* uncompressed or compressed */ |
54 | // end of header, now comes the payload | 54 | /* end of header, now comes the payload */ |
55 | } tImageHeader; | 55 | } tImageHeader; |
56 | 56 | ||
57 | 57 | /* result of the CheckFirmwareFile() function */ | |
58 | // result of the CheckFirmwareFile() function | ||
59 | typedef enum | 58 | typedef enum |
60 | { | 59 | { |
61 | eOK = 0, | 60 | eOK = 0, |
62 | eFileNotFound, // errors from here on | 61 | eFileNotFound, /* errors from here on */ |
63 | eTooBig, | 62 | eTooBig, |
64 | eTooSmall, | 63 | eTooSmall, |
65 | eReadErr, | 64 | eReadErr, |
66 | eNotUCL, | 65 | eNotUCL, |
67 | eWrongAlgorithm, | 66 | eWrongAlgorithm, |
68 | eMultiBlocks, | 67 | eMultiBlocks, |
69 | } tCheckResult; | 68 | } tCheckResult; |
70 | 69 | ||
71 | typedef struct | 70 | typedef struct |
72 | { | 71 | { |
73 | UINT8 manufacturer; | 72 | UINT8 manufacturer; |
74 | UINT8 id; | 73 | UINT8 id; |
75 | int size; | 74 | int size; |
76 | char name[32]; | 75 | char name[32]; |
77 | } tFlashInfo; | 76 | } tFlashInfo; |
78 | 77 | ||
79 | static struct plugin_api* rb; // here is a global api struct pointer | 78 | static struct plugin_api* rb; /* here is a global api struct pointer */ |
80 | |||
81 | #define SEC_SIZE 4096 // size of one flash sector | ||
82 | static UINT8 sector[SEC_SIZE]; // better not place this on the stack... | ||
83 | 79 | ||
80 | #define SEC_SIZE 4096 /* size of one flash sector */ | ||
81 | static UINT8 sector[SEC_SIZE]; /* better not place this on the stack... */ | ||
84 | 82 | ||
85 | /***************** Flash Functions *****************/ | 83 | /***************** Flash Functions *****************/ |
86 | 84 | ||
87 | 85 | ||
88 | // read the manufacturer and device ID | 86 | /* read the manufacturer and device ID */ |
89 | bool ReadID(volatile UINT8* pBase, UINT8* pManufacturerID, UINT8* pDeviceID) | 87 | bool ReadID(volatile UINT8* pBase, UINT8* pManufacturerID, UINT8* pDeviceID) |
90 | { | 88 | { |
91 | UINT8 not_manu, not_id; // read values before switching to ID mode | 89 | UINT8 not_manu, not_id; /* read values before switching to ID mode */ |
92 | UINT8 manu, id; // read values when in ID mode | 90 | UINT8 manu, id; /* read values when in ID mode */ |
93 | 91 | ||
94 | pBase = (UINT8*)((UINT32)pBase & 0xFFF80000); // round down to 512k align, to make shure | 92 | pBase = (UINT8*)((UINT32)pBase & 0xFFF80000); /* round down to 512k align, |
95 | 93 | to make sure */ | |
96 | not_manu = pBase[0]; // read the normal content | 94 | |
97 | not_id = pBase[1]; // should be 'A' (0x41) and 'R' (0x52) from the "ARCH" marker | 95 | not_manu = pBase[0]; /* read the normal content */ |
98 | 96 | not_id = pBase[1]; /* should be 'A' (0x41) and 'R' (0x52) from the | |
99 | pBase[0x5555] = 0xAA; // enter command mode | 97 | "ARCH" marker */ |
100 | pBase[0x2AAA] = 0x55; | 98 | |
101 | pBase[0x5555] = 0x90; // ID command | 99 | pBase[0x5555] = 0xAA; /* enter command mode */ |
102 | rb->sleep(HZ/50); // Atmel wants 20ms pause here | 100 | pBase[0x2AAA] = 0x55; |
103 | 101 | pBase[0x5555] = 0x90; /* ID command */ | |
104 | manu = pBase[0]; | 102 | rb->sleep(HZ/50); /* Atmel wants 20ms pause here */ |
105 | id = pBase[1]; | 103 | |
106 | 104 | manu = pBase[0]; | |
107 | pBase[0] = 0xF0; // reset flash (back to normal read mode) | 105 | id = pBase[1]; |
108 | rb->sleep(HZ/50); // Atmel wants 20ms pause here | 106 | |
109 | 107 | pBase[0] = 0xF0; /* reset flash (back to normal read mode) */ | |
110 | /* I assume success if the obtained values are different from | 108 | rb->sleep(HZ/50); /* Atmel wants 20ms pause here */ |
111 | the normal flash content. This is not perfectly bulletproof, they | 109 | |
112 | could theoretically be the same by chance, causing us to fail. */ | 110 | /* I assume success if the obtained values are different from |
113 | if (not_manu != manu || not_id != id) // a value has changed | 111 | the normal flash content. This is not perfectly bulletproof, they |
114 | { | 112 | could theoretically be the same by chance, causing us to fail. */ |
115 | *pManufacturerID = manu; // return the results | 113 | if (not_manu != manu || not_id != id) /* a value has changed */ |
116 | *pDeviceID = id; | 114 | { |
117 | return true; // success | 115 | *pManufacturerID = manu; /* return the results */ |
118 | } | 116 | *pDeviceID = id; |
119 | return false; // fail | 117 | return true; /* success */ |
118 | } | ||
119 | return false; /* fail */ | ||
120 | } | 120 | } |
121 | 121 | ||
122 | 122 | /* eraze the sector which contains the given address */ | |
123 | // eraze the sector which contains the given address | ||
124 | bool ErazeSector(volatile UINT8* pAddr) | 123 | bool ErazeSector(volatile UINT8* pAddr) |
125 | { | 124 | { |
126 | volatile UINT8* pBase = (UINT8*)((UINT32)pAddr & 0xFFF80000); // round down to 512k align | 125 | volatile UINT8* pBase = |
127 | unsigned timeout = 43000; // the timeout loop should be no less than 25ms | 126 | (UINT8*)((UINT32)pAddr & 0xFFF80000); /* round down to 512k align */ |
128 | 127 | unsigned timeout = 43000; /* the timeout loop should be no less than | |
129 | pBase[0x5555] = 0xAA; // enter command mode | 128 | 25ms */ |
130 | pBase[0x2AAA] = 0x55; | 129 | |
131 | pBase[0x5555] = 0x80; // eraze command | 130 | pBase[0x5555] = 0xAA; /* enter command mode */ |
132 | pBase[0x5555] = 0xAA; // enter command mode | 131 | pBase[0x2AAA] = 0x55; |
133 | pBase[0x2AAA] = 0x55; | 132 | pBase[0x5555] = 0x80; /* eraze command */ |
134 | *pAddr = 0x30; // eraze the sector | 133 | pBase[0x5555] = 0xAA; /* enter command mode */ |
135 | 134 | pBase[0x2AAA] = 0x55; | |
136 | // I counted 7 instructions for this loop -> min. 0.58 us per round | 135 | *pAddr = 0x30; /* eraze the sector */ |
137 | // Plus memory waitstates it will be much more, gives margin | 136 | |
138 | while (*pAddr != 0xFF && --timeout); // poll for erazed | 137 | /* I counted 7 instructions for this loop -> min. 0.58 us per round |
139 | 138 | Plus memory waitstates it will be much more, gives margin */ | |
140 | return (timeout != 0); | 139 | while (*pAddr != 0xFF && --timeout); /* poll for erazed */ |
140 | |||
141 | return (timeout != 0); | ||
141 | } | 142 | } |
142 | 143 | ||
143 | // address must be in an erazed location | 144 | /* address must be in an erazed location */ |
144 | inline bool ProgramByte(volatile UINT8* pAddr, UINT8 data) | 145 | inline bool ProgramByte(volatile UINT8* pAddr, UINT8 data) |
145 | { | 146 | { |
146 | unsigned timeout = 35; // the timeout loop should be no less than 20us | 147 | unsigned timeout = 35; /* the timeout loop should be no less than 20us */ |
147 | 148 | ||
148 | if (~*pAddr & data) // just a safety feature, not really necessary | 149 | if (~*pAddr & data) /* just a safety feature, not really necessary */ |
149 | return false; // can't set any bit from 0 to 1 | 150 | return false; /* can't set any bit from 0 to 1 */ |
150 | 151 | ||
151 | FB[0x5555] = 0xAA; // enter command mode | 152 | FB[0x5555] = 0xAA; /* enter command mode */ |
152 | FB[0x2AAA] = 0x55; | 153 | FB[0x2AAA] = 0x55; |
153 | FB[0x5555] = 0xA0; // byte program command | 154 | FB[0x5555] = 0xA0; /* byte program command */ |
154 | 155 | ||
155 | *pAddr = data; | 156 | *pAddr = data; |
156 | 157 | ||
157 | // I counted 7 instructions for this loop -> min. 0.58 us per round | 158 | /* I counted 7 instructions for this loop -> min. 0.58 us per round |
158 | // Plus memory waitstates it will be much more, gives margin | 159 | Plus memory waitstates it will be much more, gives margin */ |
159 | while (*pAddr != data && --timeout); // poll for programmed | 160 | while (*pAddr != data && --timeout); /* poll for programmed */ |
160 | 161 | ||
161 | return (timeout != 0); | 162 | return (timeout != 0); |
162 | } | 163 | } |
163 | 164 | ||
164 | // this returns true if supported and fills the info struct | 165 | /* this returns true if supported and fills the info struct */ |
165 | bool GetFlashInfo(tFlashInfo* pInfo) | 166 | bool GetFlashInfo(tFlashInfo* pInfo) |
166 | { | 167 | { |
167 | rb->memset(pInfo, 0, sizeof(tFlashInfo)); | 168 | rb->memset(pInfo, 0, sizeof(tFlashInfo)); |
168 | 169 | ||
169 | if (!ReadID(FB, &pInfo->manufacturer, &pInfo->id)) | 170 | if (!ReadID(FB, &pInfo->manufacturer, &pInfo->id)) |
170 | return false; | 171 | return false; |
171 | 172 | ||
172 | if (pInfo->manufacturer == 0xBF) // SST | 173 | if (pInfo->manufacturer == 0xBF) /* SST */ |
173 | { | 174 | { |
174 | if (pInfo->id == 0xD6) | 175 | if (pInfo->id == 0xD6) |
175 | { | 176 | { |
176 | pInfo->size = 256* 1024; // 256k | 177 | pInfo->size = 256* 1024; /* 256k */ |
177 | rb->strcpy(pInfo->name, "SST39VF020"); | 178 | rb->strcpy(pInfo->name, "SST39VF020"); |
178 | return true; | 179 | return true; |
179 | } | 180 | } |
180 | else if (pInfo->id == 0xD7) | 181 | else if (pInfo->id == 0xD7) |
181 | { | 182 | { |
182 | pInfo->size = 512* 1024; // 512k | 183 | pInfo->size = 512* 1024; /* 512k */ |
183 | rb->strcpy(pInfo->name, "SST39VF040"); | 184 | rb->strcpy(pInfo->name, "SST39VF040"); |
184 | return true; | 185 | return true; |
185 | } | 186 | } |
186 | else | 187 | else |
187 | return false; | 188 | return false; |
188 | } | 189 | } |
189 | return false; | 190 | return false; |
190 | } | 191 | } |
191 | 192 | ||
192 | 193 | ||
193 | /*********** Tool Functions ************/ | 194 | /*********** Tool Functions ************/ |
194 | 195 | ||
195 | // place a 32 bit value into memory, big endian | 196 | /* place a 32 bit value into memory, big endian */ |
196 | void Write32(UINT8* pByte, UINT32 value) | 197 | void Write32(UINT8* pByte, UINT32 value) |
197 | { | 198 | { |
198 | pByte[0] = (UINT8)(value >> 24); | 199 | pByte[0] = (UINT8)(value >> 24); |
199 | pByte[1] = (UINT8)(value >> 16); | 200 | pByte[1] = (UINT8)(value >> 16); |
200 | pByte[2] = (UINT8)(value >> 8); | 201 | pByte[2] = (UINT8)(value >> 8); |
201 | pByte[3] = (UINT8)(value); | 202 | pByte[3] = (UINT8)(value); |
202 | } | 203 | } |
203 | 204 | ||
204 | // read a 32 bit value from memory, big endian | 205 | /* read a 32 bit value from memory, big endian */ |
205 | UINT32 Read32(UINT8* pByte) | 206 | UINT32 Read32(UINT8* pByte) |
206 | { | 207 | { |
207 | UINT32 value = 0; | 208 | UINT32 value; |
208 | 209 | ||
209 | value |= (UINT32)pByte[0] << 24; | 210 | value = (UINT32)pByte[0] << 24; |
210 | value |= (UINT32)pByte[1] << 16; | 211 | value |= (UINT32)pByte[1] << 16; |
211 | value |= (UINT32)pByte[2] << 8; | 212 | value |= (UINT32)pByte[2] << 8; |
212 | value |= (UINT32)pByte[3]; | 213 | value |= (UINT32)pByte[3]; |
213 | 214 | ||
214 | return value; | 215 | return value; |
215 | } | 216 | } |
216 | 217 | ||
217 | 218 | /* get the start address of the second image */ | |
218 | // get the start address of the second image | ||
219 | tImageHeader* GetSecondImage(void) | 219 | tImageHeader* GetSecondImage(void) |
220 | { | 220 | { |
221 | tImageHeader* pImage1; | 221 | tImageHeader* pImage1; |
222 | UINT32 pos = 0; // dafault: not found | 222 | UINT32 pos = 0; /* default: not found */ |
223 | UINT32* pFlash = (UINT32*)FB; | 223 | UINT32* pFlash = (UINT32*)FB; |
224 | 224 | ||
225 | UINT16 version = *(UINT16*)(FB + VERS_ADR); | 225 | UINT16 version = *(UINT16*)(FB + VERS_ADR); |
226 | if (version < 200) // at least 2.00 | 226 | if (version < 200) /* at least 2.00 */ |
227 | { | 227 | { |
228 | return 0; // not our flash layout | 228 | return 0; /* not our flash layout */ |
229 | } | 229 | } |
230 | 230 | ||
231 | // determine the first image position | 231 | /* determine the first image position */ |
232 | pos = pFlash[2] + pFlash[3]; // position + size of the bootloader = after it | 232 | pos = pFlash[2] + pFlash[3]; /* position + size of the bootloader = after |
233 | pos = (pos + 3) & ~3; // be shure it's 32 bit aligned | 233 | it */ |
234 | pImage1 = (tImageHeader*)pos; | 234 | pos = (pos + 3) & ~3; /* be sure it's 32 bit aligned */ |
235 | 235 | pImage1 = (tImageHeader*)pos; | |
236 | if (pImage1->destination != ROCKBOX_DEST || pImage1->execute != ROCKBOX_EXEC) | 236 | |
237 | return 0; // seems to be no Rockbox stuff in here | 237 | if (pImage1->destination != ROCKBOX_DEST || |
238 | 238 | pImage1->execute != ROCKBOX_EXEC) | |
239 | if (pImage1->size != 0) | 239 | return 0; /* seems to be no Rockbox stuff in here */ |
240 | { // success, we have a second image | 240 | |
241 | pos = (UINT32)pImage1 + sizeof(tImageHeader) + pImage1->size; | 241 | if (pImage1->size != 0) |
242 | if (((pos + SECTORSIZE-1) & ~(SECTORSIZE-1)) != pos) | 242 | { |
243 | { // not sector-aligned | 243 | /* success, we have a second image */ |
244 | pos = 0; // sanity check failed | 244 | pos = (UINT32)pImage1 + sizeof(tImageHeader) + pImage1->size; |
245 | } | 245 | if (((pos + SECTORSIZE-1) & ~(SECTORSIZE-1)) != pos) |
246 | } | 246 | { /* not sector-aligned */ |
247 | 247 | pos = 0; // sanity check failed | |
248 | return (tImageHeader*)pos; | 248 | } |
249 | } | ||
250 | |||
251 | return (tImageHeader*)pos; | ||
249 | } | 252 | } |
250 | 253 | ||
251 | 254 | ||
252 | /*********** Image File Functions ************/ | 255 | /*********** Image File Functions ************/ |
253 | 256 | ||
254 | // so far, only compressed images in UCL NRV algorithm 2e supported | 257 | /* so far, only compressed images in UCL NRV algorithm 2e supported */ |
255 | tCheckResult CheckImageFile(char* filename, int space, tImageHeader* pHeader) | 258 | tCheckResult CheckImageFile(char* filename, int space, tImageHeader* pHeader) |
256 | { | 259 | { |
257 | int i; | 260 | int i; |
258 | int fd; | 261 | int fd; |
259 | int filesize; // size info | 262 | int filesize; /* size info */ |
260 | 263 | ||
261 | int fileread = 0; // total size as read from the file | 264 | int fileread = 0; /* total size as read from the file */ |
262 | int read; // how many for this sector | 265 | int read; /* how many for this sector */ |
263 | 266 | ||
264 | // magic file header for compressed files | 267 | /* magic file header for compressed files */ |
265 | static const UINT8 magic[8] = { 0x00,0xe9,0x55,0x43,0x4c,0xff,0x01,0x1a }; | 268 | static const UINT8 magic[8] = { 0x00,0xe9,0x55,0x43,0x4c,0xff,0x01,0x1a }; |
266 | UINT8 ucl_header[UCL_HEADER]; | 269 | UINT8 ucl_header[UCL_HEADER]; |
267 | 270 | ||
268 | fd = rb->open(filename, O_RDONLY); | 271 | fd = rb->open(filename, O_RDONLY); |
269 | if (fd < 0) | 272 | if (fd < 0) |
270 | return eFileNotFound; | 273 | return eFileNotFound; |
271 | 274 | ||
272 | filesize = rb->filesize(fd); | 275 | filesize = rb->filesize(fd); |
273 | if (filesize - (int)sizeof(ucl_header) - 8 > space) | 276 | if (filesize - (int)sizeof(ucl_header) - 8 > space) |
274 | { | 277 | { |
275 | rb->close(fd); | 278 | rb->close(fd); |
276 | return eTooBig; | 279 | return eTooBig; |
277 | } | 280 | } |
278 | else if (filesize < 50000) // give it some reasonable lower limit | 281 | else if (filesize < 50000) /* give it some reasonable lower limit */ |
279 | { | 282 | { |
280 | rb->close(fd); | 283 | rb->close(fd); |
281 | return eTooSmall; | 284 | return eTooSmall; |
282 | } | 285 | } |
283 | 286 | ||
284 | // do some sanity checks | 287 | /* do some sanity checks */ |
285 | 288 | ||
286 | read = rb->read(fd, ucl_header, sizeof(ucl_header)); | 289 | read = rb->read(fd, ucl_header, sizeof(ucl_header)); |
287 | fileread += read; | 290 | fileread += read; |
288 | if (read != sizeof(ucl_header)) | 291 | if (read != sizeof(ucl_header)) |
289 | { | 292 | { |
290 | rb->close(fd); | 293 | rb->close(fd); |
291 | return eReadErr; | 294 | return eReadErr; |
292 | } | 295 | } |
293 | 296 | ||
294 | // compare the magic header | 297 | /* compare the magic header */ |
295 | for (i=0; i<8; i++) | 298 | for (i=0; i<8; i++) |
296 | { | 299 | { |
297 | if (ucl_header[i] != magic[i]) | 300 | if (ucl_header[i] != magic[i]) |
298 | { | 301 | { |
299 | rb->close(fd); | 302 | rb->close(fd); |
300 | return eNotUCL; | 303 | return eNotUCL; |
301 | } | 304 | } |
302 | } | 305 | } |
303 | 306 | ||
304 | // check for supported algorithm | 307 | /* check for supported algorithm */ |
305 | if (ucl_header[12] != 0x2E) | 308 | if (ucl_header[12] != 0x2E) |
306 | { | 309 | { |
307 | rb->close(fd); | 310 | rb->close(fd); |
308 | return eWrongAlgorithm; | 311 | return eWrongAlgorithm; |
309 | } | 312 | } |
310 | 313 | ||
311 | pHeader->size = Read32(ucl_header + 22); // compressed size | 314 | pHeader->size = Read32(ucl_header + 22); /* compressed size */ |
312 | if (pHeader->size != filesize - sizeof(ucl_header) - 8) | 315 | if (pHeader->size != filesize - sizeof(ucl_header) - 8) |
313 | { | 316 | { |
314 | rb->close(fd); | 317 | rb->close(fd); |
315 | return eMultiBlocks; | 318 | return eMultiBlocks; |
316 | } | 319 | } |
317 | 320 | ||
318 | if (Read32(ucl_header + 18) > pHeader->size) // compare with uncompressed size | 321 | if (Read32(ucl_header + 18) > pHeader->size) /* compare with uncompressed |
319 | { // normal case | 322 | size */ |
320 | pHeader->flags = 0x00000001; // flags for UCL compressed | 323 | { /* normal case */ |
321 | } | 324 | pHeader->flags = 0x00000001; /* flags for UCL compressed */ |
322 | else | 325 | } |
323 | { | 326 | else |
324 | pHeader->flags = 0x00000000; // very unlikely, content was not compressible | 327 | { |
325 | } | 328 | pHeader->flags = 0x00000000; /* very unlikely, content was not |
326 | 329 | compressible */ | |
327 | // check if we can read the whole file | 330 | } |
328 | do | 331 | |
329 | { | 332 | /* check if we can read the whole file */ |
330 | read = rb->read(fd, sector, SEC_SIZE); | 333 | do |
331 | fileread += read; | 334 | { |
332 | } while (read == SEC_SIZE); | 335 | read = rb->read(fd, sector, SEC_SIZE); |
333 | 336 | fileread += read; | |
334 | rb->close(fd); | 337 | } while (read == SEC_SIZE); |
335 | 338 | ||
336 | if (fileread != filesize) | 339 | rb->close(fd); |
337 | return eReadErr; | 340 | |
338 | 341 | if (fileread != filesize) | |
339 | // fill in the hardcoded rest of the header | 342 | return eReadErr; |
340 | pHeader->destination = ROCKBOX_DEST; | 343 | |
341 | pHeader->execute = ROCKBOX_EXEC; | 344 | /* fill in the hardcoded rest of the header */ |
342 | 345 | pHeader->destination = ROCKBOX_DEST; | |
343 | return eOK; | 346 | pHeader->execute = ROCKBOX_EXEC; |
347 | |||
348 | return eOK; | ||
344 | } | 349 | } |
345 | 350 | ||
346 | 351 | ||
347 | // returns the # of failures, 0 on success | 352 | /* returns the # of failures, 0 on success */ |
348 | unsigned ProgramImageFile(char* filename, UINT8* pos, tImageHeader* pImageHeader, int start, int size) | 353 | unsigned ProgramImageFile(char* filename, UINT8* pos, |
354 | tImageHeader* pImageHeader, int start, int size) | ||
349 | { | 355 | { |
350 | int i; | 356 | int i; |
351 | int fd; | 357 | int fd; |
352 | int read; // how many for this sector | 358 | int read; /* how many for this sector */ |
353 | unsigned failures = 0; | 359 | unsigned failures = 0; |
354 | 360 | ||
355 | fd = rb->open(filename, O_RDONLY); | 361 | fd = rb->open(filename, O_RDONLY); |
356 | if (fd < 0) | 362 | if (fd < 0) |
357 | return false; | 363 | return false; |
358 | 364 | ||
359 | // no error checking necessary here, we checked for minimum size already | 365 | /* no error checking necessary here, we checked for minimum size |
360 | rb->lseek(fd, start, SEEK_SET); // go to start position | 366 | already */ |
361 | 367 | rb->lseek(fd, start, SEEK_SET); /* go to start position */ | |
362 | *(tImageHeader*)sector = *pImageHeader; // copy header into sector buffer | 368 | |
363 | read = rb->read(fd, sector + sizeof(tImageHeader), SEC_SIZE - sizeof(tImageHeader)); // payload behind | 369 | *(tImageHeader*)sector = *pImageHeader; /* copy header into sector |
364 | size -= read; | 370 | buffer */ |
365 | read += sizeof(tImageHeader); // to be programmed, but not part of the file | 371 | read = rb->read(fd, sector + sizeof(tImageHeader), |
366 | 372 | SEC_SIZE - sizeof(tImageHeader)); /* payload behind */ | |
367 | do | 373 | size -= read; |
368 | { | 374 | read += sizeof(tImageHeader); /* to be programmed, but not part of the |
369 | if (!ErazeSector(pos)) | 375 | file */ |
370 | { | 376 | |
371 | // nothing we can do, let the programming count the errors | 377 | do { |
372 | } | 378 | if (!ErazeSector(pos)) |
373 | 379 | { | |
374 | for (i=0; i<read; i++) | 380 | /* nothing we can do, let the programming count the errors */ |
375 | { | 381 | } |
376 | if (!ProgramByte(pos + i, sector[i])) | 382 | |
377 | { | 383 | for (i=0; i<read; i++) |
378 | failures++; | 384 | { |
379 | } | 385 | if (!ProgramByte(pos + i, sector[i])) |
380 | } | 386 | { |
381 | 387 | failures++; | |
382 | pos += SEC_SIZE; | 388 | } |
383 | read = rb->read(fd, sector, (size > SEC_SIZE) ? SEC_SIZE : size); // payload for next sector | 389 | } |
384 | size -= read; | 390 | |
385 | } while (read > 0); | 391 | pos += SEC_SIZE; |
386 | 392 | read = rb->read(fd, sector, (size > SEC_SIZE) ? SEC_SIZE : size); | |
387 | rb->close(fd); | 393 | /* payload for next sector */ |
388 | 394 | size -= read; | |
389 | return failures; | 395 | } while (read > 0); |
396 | |||
397 | rb->close(fd); | ||
398 | |||
399 | return failures; | ||
390 | } | 400 | } |
391 | 401 | ||
392 | // returns the # of failures, 0 on success | 402 | /* returns the # of failures, 0 on success */ |
393 | unsigned VerifyImageFile(char* filename, UINT8* pos, tImageHeader* pImageHeader, int start, int size) | 403 | unsigned VerifyImageFile(char* filename, UINT8* pos, |
404 | tImageHeader* pImageHeader, int start, int size) | ||
394 | { | 405 | { |
395 | int i; | 406 | int i; |
396 | int fd; | 407 | int fd; |
397 | int read; // how many for this sector | 408 | int read; /* how many for this sector */ |
398 | unsigned failures = 0; | 409 | unsigned failures = 0; |
399 | 410 | ||
400 | fd = rb->open(filename, O_RDONLY); | 411 | fd = rb->open(filename, O_RDONLY); |
401 | if (fd < 0) | 412 | if (fd < 0) |
402 | return false; | 413 | return false; |
403 | 414 | ||
404 | // no error checking necessary here, we checked for minimum size already | 415 | /* no error checking necessary here, we checked for minimum size |
405 | rb->lseek(fd, start, SEEK_SET); // go to start position | 416 | already */ |
406 | 417 | rb->lseek(fd, start, SEEK_SET); /* go to start position */ | |
407 | *(tImageHeader*)sector = *pImageHeader; // copy header into sector buffer | 418 | |
408 | read = rb->read(fd, sector + sizeof(tImageHeader), SEC_SIZE - sizeof(tImageHeader)); // payload behind | 419 | *(tImageHeader*)sector = *pImageHeader; /* copy header into sector |
409 | size -= read; | 420 | buffer */ |
410 | read += sizeof(tImageHeader); // to be programmed, but not part of the file | 421 | read = rb->read(fd, sector + sizeof(tImageHeader), |
411 | 422 | SEC_SIZE - sizeof(tImageHeader)); /* payload behind */ | |
412 | do | 423 | |
413 | { | 424 | size -= read; |
414 | for (i=0; i<read; i++) | 425 | read += sizeof(tImageHeader); /* to be programmed, but not part of the |
415 | { | 426 | file */ |
416 | if (pos[i] != sector[i]) | 427 | |
417 | { | 428 | do |
418 | failures++; | 429 | { |
419 | } | 430 | for (i=0; i<read; i++) |
420 | } | 431 | { |
421 | 432 | if (pos[i] != sector[i]) | |
422 | pos += SEC_SIZE; | 433 | { |
423 | read = rb->read(fd, sector, (size > SEC_SIZE) ? SEC_SIZE : size); // payload for next sector | 434 | failures++; |
424 | size -= read; | 435 | } |
425 | } while (read); | 436 | } |
426 | 437 | ||
427 | rb->close(fd); | 438 | pos += SEC_SIZE; |
428 | 439 | read = rb->read(fd, sector, (size > SEC_SIZE) ? SEC_SIZE : size); | |
429 | return failures; | 440 | /* payload for next sector */ |
441 | size -= read; | ||
442 | } while (read); | ||
443 | |||
444 | rb->close(fd); | ||
445 | |||
446 | return failures; | ||
430 | } | 447 | } |
431 | 448 | ||
432 | 449 | ||
@@ -435,235 +452,240 @@ unsigned VerifyImageFile(char* filename, UINT8* pos, tImageHeader* pImageHeader, | |||
435 | 452 | ||
436 | #ifdef HAVE_LCD_BITMAP | 453 | #ifdef HAVE_LCD_BITMAP |
437 | 454 | ||
438 | // helper for DoUserDialog() | 455 | /* helper for DoUserDialog() */ |
439 | void ShowFlashInfo(tFlashInfo* pInfo, tImageHeader* pImageHeader) | 456 | void ShowFlashInfo(tFlashInfo* pInfo, tImageHeader* pImageHeader) |
440 | { | 457 | { |
441 | char buf[32]; | 458 | char buf[32]; |
442 | 459 | ||
443 | if (!pInfo->manufacturer) | 460 | if (!pInfo->manufacturer) |
444 | { | 461 | { |
445 | rb->lcd_puts(0, 0, "Flash: M=?? D=??"); | 462 | rb->lcd_puts(0, 0, "Flash: M=?? D=??"); |
446 | } | 463 | } |
464 | else | ||
465 | { | ||
466 | if (pInfo->size) | ||
467 | { | ||
468 | rb->snprintf(buf, sizeof(buf), "Flash size: %d KB", | ||
469 | pInfo->size / 1024); | ||
470 | rb->lcd_puts(0, 0, buf); | ||
471 | } | ||
472 | else | ||
473 | { | ||
474 | rb->lcd_puts(0, 0, "Unsupported chip"); | ||
475 | } | ||
476 | |||
477 | } | ||
478 | |||
479 | if (pImageHeader) | ||
480 | { | ||
481 | rb->snprintf(buf, sizeof(buf), "Image at %d KB", | ||
482 | ((UINT8*)pImageHeader - FB) / 1024); | ||
483 | rb->lcd_puts(0, 1, buf); | ||
484 | } | ||
447 | else | 485 | else |
448 | { | 486 | { |
449 | if (pInfo->size) | 487 | rb->lcd_puts(0, 1, "No image found!"); |
450 | { | ||
451 | rb->snprintf(buf, sizeof(buf), "Flash size: %d KB", pInfo->size / 1024); | ||
452 | rb->lcd_puts(0, 0, buf); | ||
453 | } | ||
454 | else | ||
455 | { | ||
456 | rb->lcd_puts(0, 0, "Unsupported chip"); | ||
457 | } | ||
458 | |||
459 | } | ||
460 | |||
461 | if (pImageHeader) | ||
462 | { | ||
463 | rb->snprintf(buf, sizeof(buf), "Image at %d KB", ((UINT8*)pImageHeader - FB) / 1024); | ||
464 | rb->lcd_puts(0, 1, buf); | ||
465 | } | 488 | } |
466 | else | 489 | |
467 | { | 490 | rb->lcd_update(); |
468 | rb->lcd_puts(0, 1, "No image found!"); | ||
469 | } | ||
470 | |||
471 | rb->lcd_update(); | ||
472 | } | 491 | } |
473 | 492 | ||
474 | 493 | ||
475 | // Kind of our main function, defines the application flow. | 494 | /* Kind of our main function, defines the application flow. */ |
476 | void DoUserDialog(void) | 495 | void DoUserDialog(void) |
477 | { | 496 | { |
478 | tImageHeader ImageHeader; | 497 | tImageHeader ImageHeader; |
479 | tFlashInfo FlashInfo; | 498 | tFlashInfo FlashInfo; |
480 | char buf[32]; | 499 | char buf[32]; |
481 | int button; | 500 | int button; |
482 | int rc; // generic return code | 501 | int rc; /* generic return code */ |
483 | UINT32 space, aligned_size, true_size; | 502 | UINT32 space, aligned_size, true_size; |
484 | UINT8* pos; | 503 | UINT8* pos; |
485 | 504 | ||
486 | rb->lcd_setfont(FONT_SYSFIXED); | 505 | rb->lcd_setfont(FONT_SYSFIXED); |
487 | 506 | ||
488 | pos = (void*)GetSecondImage(); | 507 | pos = (void*)GetSecondImage(); |
489 | rc = GetFlashInfo(&FlashInfo); | 508 | rc = GetFlashInfo(&FlashInfo); |
490 | 509 | ||
491 | ShowFlashInfo(&FlashInfo, (void*)pos); | 510 | ShowFlashInfo(&FlashInfo, (void*)pos); |
492 | if (FlashInfo.size == 0) // no valid chip | 511 | if (FlashInfo.size == 0) /* no valid chip */ |
493 | { | 512 | { |
494 | rb->splash(HZ*3, 0, true, "Not flashable"); | 513 | rb->splash(HZ*3, 0, true, "Not flashable"); |
495 | return; // exit | 514 | return; /* exit */ |
496 | } | 515 | } |
497 | else if (pos == 0) | 516 | else if (pos == 0) |
498 | { | 517 | { |
499 | rb->splash(HZ*3, 0, true, "No Image"); | 518 | rb->splash(HZ*3, 0, true, "No Image"); |
500 | return; // exit | 519 | return; /* exit */ |
501 | } | 520 | } |
502 | 521 | ||
503 | rb->lcd_puts(0, 3, "using file:"); | 522 | rb->lcd_puts(0, 3, "using file:"); |
504 | rb->lcd_puts(0, 4, FILENAME); | 523 | rb->lcd_puts(0, 4, FILENAME); |
505 | rb->lcd_puts(0, 6, "[F1] to check file"); | 524 | rb->lcd_puts(0, 6, "[F1] to check file"); |
506 | rb->lcd_puts(0, 7, "other key to exit"); | 525 | rb->lcd_puts(0, 7, "other key to exit"); |
507 | rb->lcd_update(); | 526 | rb->lcd_update(); |
508 | 527 | ||
509 | button = rb->button_get(true); | 528 | button = rb->button_get(true); |
510 | button = rb->button_get(true); | 529 | button = rb->button_get(true); |
511 | 530 | ||
512 | if (button != BUTTON_F1) | 531 | if (button != BUTTON_F1) |
513 | { | 532 | { |
514 | return; | 533 | return; |
515 | } | 534 | } |
516 | 535 | ||
517 | rb->lcd_clear_display(); | 536 | rb->lcd_clear_display(); |
518 | rb->lcd_puts(0, 0, "checking..."); | 537 | rb->lcd_puts(0, 0, "checking..."); |
519 | rb->lcd_update(); | 538 | rb->lcd_update(); |
520 | 539 | ||
521 | space = FlashInfo.size - (pos-FB + sizeof(ImageHeader)); // size minus start | 540 | space = FlashInfo.size - (pos-FB + sizeof(ImageHeader)); |
522 | rc = CheckImageFile(FILENAME, space, &ImageHeader); | 541 | /* size minus start */ |
523 | rb->lcd_puts(0, 0, "checked:"); | 542 | |
524 | switch (rc) | 543 | rc = CheckImageFile(FILENAME, space, &ImageHeader); |
525 | { | 544 | rb->lcd_puts(0, 0, "checked:"); |
526 | case eOK: | 545 | switch (rc) { |
527 | rb->lcd_puts(0, 1, "File OK."); | 546 | case eOK: |
528 | break; | 547 | rb->lcd_puts(0, 1, "File OK."); |
548 | break; | ||
529 | case eNotUCL: | 549 | case eNotUCL: |
530 | rb->lcd_puts(0, 1, "File not UCL "); | 550 | rb->lcd_puts(0, 1, "File not UCL "); |
531 | rb->lcd_puts(0, 2, "compressed."); | 551 | rb->lcd_puts(0, 2, "compressed."); |
532 | rb->lcd_puts(0, 3, "Use uclpack --2e"); | 552 | rb->lcd_puts(0, 3, "Use uclpack --2e"); |
533 | rb->lcd_puts(0, 4, " --10 rockbox.bin"); | 553 | rb->lcd_puts(0, 4, " --10 rockbox.bin"); |
534 | break; | 554 | break; |
535 | case eWrongAlgorithm: | 555 | case eWrongAlgorithm: |
536 | rb->lcd_puts(0, 1, "Wrong algorithm"); | 556 | rb->lcd_puts(0, 1, "Wrong algorithm"); |
537 | rb->lcd_puts(0, 2, "for compression."); | 557 | rb->lcd_puts(0, 2, "for compression."); |
538 | rb->lcd_puts(0, 3, "Use uclpack --2e"); | 558 | rb->lcd_puts(0, 3, "Use uclpack --2e"); |
539 | rb->lcd_puts(0, 4, " --10 rockbox.bin"); | 559 | rb->lcd_puts(0, 4, " --10 rockbox.bin"); |
540 | break; | 560 | break; |
541 | case eFileNotFound: | 561 | case eFileNotFound: |
542 | rb->lcd_puts(0, 1, "File not found."); | 562 | rb->lcd_puts(0, 1, "File not found."); |
543 | rb->lcd_puts(0, 2, "Put this in root:"); | 563 | rb->lcd_puts(0, 2, "Put this in root:"); |
544 | rb->lcd_puts(0, 4, FILENAME); | 564 | rb->lcd_puts(0, 4, FILENAME); |
545 | break; | 565 | break; |
546 | case eTooBig: | 566 | case eTooBig: |
547 | rb->lcd_puts(0, 1, "File too big,"); | 567 | rb->lcd_puts(0, 1, "File too big,"); |
548 | rb->lcd_puts(0, 2, "won't fit in chip."); | 568 | rb->lcd_puts(0, 2, "won't fit in chip."); |
549 | break; | 569 | break; |
550 | case eTooSmall: | 570 | case eTooSmall: |
551 | rb->lcd_puts(0, 1, "File too small."); | 571 | rb->lcd_puts(0, 1, "File too small."); |
552 | rb->lcd_puts(0, 2, "Incomplete?"); | 572 | rb->lcd_puts(0, 2, "Incomplete?"); |
553 | break; | 573 | break; |
554 | case eReadErr: | 574 | case eReadErr: |
555 | rb->lcd_puts(0, 1, "File read error."); | 575 | rb->lcd_puts(0, 1, "File read error."); |
556 | break; | 576 | break; |
557 | case eMultiBlocks: | 577 | case eMultiBlocks: |
558 | rb->lcd_puts(0, 1, "File invalid."); | 578 | rb->lcd_puts(0, 1, "File invalid."); |
559 | rb->lcd_puts(0, 2, "Blocksize"); | 579 | rb->lcd_puts(0, 2, "Blocksize"); |
560 | rb->lcd_puts(0, 3, " too small?"); | 580 | rb->lcd_puts(0, 3, " too small?"); |
561 | break; | 581 | break; |
562 | default: | 582 | default: |
563 | rb->lcd_puts(0, 1, "Check failed."); | 583 | rb->lcd_puts(0, 1, "Check failed."); |
564 | break; | 584 | break; |
565 | } | 585 | } |
566 | 586 | ||
567 | if (rc == eOK) | 587 | if (rc == eOK) |
568 | { // was OK | 588 | { /* was OK */ |
569 | rb->lcd_puts(0, 6, "[F2] to program"); | 589 | rb->lcd_puts(0, 6, "[F2] to program"); |
570 | rb->lcd_puts(0, 7, "other key to exit"); | 590 | rb->lcd_puts(0, 7, "other key to exit"); |
571 | } | 591 | } |
572 | else | 592 | else |
573 | { // error occured | 593 | { /* error occured */ |
574 | rb->lcd_puts(0, 6, "Any key to exit"); | 594 | rb->lcd_puts(0, 6, "Any key to exit"); |
575 | } | 595 | } |
576 | 596 | ||
577 | rb->lcd_update(); | 597 | rb->lcd_update(); |
578 | 598 | ||
579 | button = rb->button_get(true); | 599 | button = rb->button_get(true); |
580 | button = rb->button_get(true); | 600 | button = rb->button_get(true); |
581 | 601 | ||
582 | if (rc != eOK || button != BUTTON_F2) | 602 | if (rc != eOK || button != BUTTON_F2) |
583 | { | 603 | { |
584 | return; | 604 | return; |
585 | } | 605 | } |
586 | 606 | ||
587 | true_size = ImageHeader.size; | 607 | true_size = ImageHeader.size; |
588 | aligned_size = ((sizeof(tImageHeader) + true_size + SECTORSIZE-1) & ~(SECTORSIZE-1)) - sizeof(tImageHeader); // round up to next flash sector | 608 | aligned_size = ((sizeof(tImageHeader) + true_size + SECTORSIZE-1) & |
589 | ImageHeader.size = aligned_size; // increase image size such that we reach the next sector | 609 | ~(SECTORSIZE-1)) - sizeof(tImageHeader); /* round up to |
590 | 610 | next flash | |
591 | rb->lcd_clear_display(); | 611 | sector */ |
592 | rb->lcd_puts(0, 0, "Programming..."); | 612 | ImageHeader.size = aligned_size; /* increase image size such that we reach |
593 | rb->lcd_update(); | 613 | the next sector */ |
594 | 614 | ||
595 | rc = ProgramImageFile(FILENAME, pos, &ImageHeader, UCL_HEADER, true_size); | 615 | rb->lcd_clear_display(); |
596 | if (rc) | 616 | rb->lcd_puts(0, 0, "Programming..."); |
597 | { // errors | 617 | rb->lcd_update(); |
598 | rb->lcd_clear_display(); | 618 | |
599 | rb->lcd_puts(0, 0, "Error:"); | 619 | rc = ProgramImageFile(FILENAME, pos, &ImageHeader, UCL_HEADER, true_size); |
600 | rb->lcd_puts(0, 1, "Programming fail!"); | 620 | if (rc) |
601 | rb->snprintf(buf, sizeof(buf), "%d errors", rc); | 621 | { /* errors */ |
602 | rb->lcd_puts(0, 2, buf); | 622 | rb->lcd_clear_display(); |
603 | rb->lcd_update(); | 623 | rb->lcd_puts(0, 0, "Error:"); |
604 | button = rb->button_get(true); | 624 | rb->lcd_puts(0, 1, "Programming fail!"); |
605 | button = rb->button_get(true); | 625 | rb->snprintf(buf, sizeof(buf), "%d errors", rc); |
606 | } | 626 | rb->lcd_puts(0, 2, buf); |
607 | 627 | rb->lcd_update(); | |
608 | rb->lcd_clear_display(); | 628 | button = rb->button_get(true); |
609 | rb->lcd_puts(0, 0, "Verifying..."); | 629 | button = rb->button_get(true); |
610 | rb->lcd_update(); | 630 | } |
611 | 631 | ||
612 | rc = VerifyImageFile(FILENAME, pos, &ImageHeader, UCL_HEADER, true_size); | 632 | rb->lcd_clear_display(); |
613 | 633 | rb->lcd_puts(0, 0, "Verifying..."); | |
614 | rb->lcd_clear_display(); | 634 | rb->lcd_update(); |
615 | if (rc == 0) | 635 | |
616 | { | 636 | rc = VerifyImageFile(FILENAME, pos, &ImageHeader, UCL_HEADER, true_size); |
617 | rb->lcd_puts(0, 0, "Verify OK."); | 637 | |
618 | } | 638 | rb->lcd_clear_display(); |
619 | else | 639 | if (rc == 0) |
620 | { | 640 | { |
621 | rb->lcd_puts(0, 0, "Error:"); | 641 | rb->lcd_puts(0, 0, "Verify OK."); |
622 | rb->lcd_puts(0, 1, "Verify fail!"); | 642 | } |
623 | rb->snprintf(buf, sizeof(buf), "%d errors", rc); | 643 | else |
624 | rb->lcd_puts(0, 2, buf); | 644 | { |
625 | rb->lcd_puts(0, 3, "Use safe image"); | 645 | rb->lcd_puts(0, 0, "Error:"); |
626 | rb->lcd_puts(0, 4, "if booting hangs:"); | 646 | rb->lcd_puts(0, 1, "Verify fail!"); |
627 | rb->lcd_puts(0, 5, "F1 during power-on"); | 647 | rb->snprintf(buf, sizeof(buf), "%d errors", rc); |
628 | } | 648 | rb->lcd_puts(0, 2, buf); |
629 | rb->lcd_puts(0, 7, "Any key to exit"); | 649 | rb->lcd_puts(0, 3, "Use safe image"); |
630 | rb->lcd_update(); | 650 | rb->lcd_puts(0, 4, "if booting hangs:"); |
631 | 651 | rb->lcd_puts(0, 5, "F1 during power-on"); | |
632 | button = rb->button_get(true); | 652 | } |
633 | button = rb->button_get(true); | 653 | rb->lcd_puts(0, 7, "Any key to exit"); |
654 | rb->lcd_update(); | ||
655 | |||
656 | button = rb->button_get(true); | ||
657 | button = rb->button_get(true); | ||
634 | } | 658 | } |
635 | 659 | ||
636 | #else // HAVE_LCD_BITMAP | 660 | #else /* HAVE_LCD_BITMAP */ |
637 | 661 | ||
638 | // Player implementation has to go here | 662 | /* Player implementation has to go here */ |
639 | void DoUserDialog(void) | 663 | void DoUserDialog(void) |
640 | { | 664 | { |
641 | } | 665 | } |
642 | 666 | ||
643 | #endif // HAVE_LCD_BITMAP | 667 | #endif /* HAVE_LCD_BITMAP */ |
644 | 668 | ||
645 | 669 | ||
646 | /***************** Plugin Entry Point *****************/ | 670 | /***************** Plugin Entry Point *****************/ |
647 | 671 | ||
648 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | 672 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) |
649 | { | 673 | { |
674 | /* this macro should be called as the first thing you do in the plugin. | ||
675 | it test that the api version and model the plugin was compiled for | ||
676 | matches the machine it is running on */ | ||
677 | TEST_PLUGIN_API(api); | ||
650 | 678 | ||
679 | /* if you don't use the parameter, you can do like | ||
680 | this to avoid the compiler warning about it */ | ||
681 | (void)parameter; | ||
682 | |||
683 | rb = api; /* copy to global api pointer */ | ||
651 | 684 | ||
652 | /* this macro should be called as the first thing you do in the plugin. | 685 | /* now go ahead and have fun! */ |
653 | it test that the api version and model the plugin was compiled for | 686 | DoUserDialog(); |
654 | matches the machine it is running on */ | ||
655 | TEST_PLUGIN_API(api); | ||
656 | |||
657 | /* if you don't use the parameter, you can do like | ||
658 | this to avoid the compiler warning about it */ | ||
659 | (void)parameter; | ||
660 | |||
661 | rb = api; /* copy to global api pointer */ | ||
662 | |||
663 | /* now go ahead and have fun! */ | ||
664 | DoUserDialog(); | ||
665 | 687 | ||
666 | return PLUGIN_OK; | 688 | return PLUGIN_OK; |
667 | } | 689 | } |
668 | 690 | ||
669 | #endif | 691 | #endif |