Rev Author Line No. Line
1144 kaklik 1  
2 /*
3 * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
4 *
5 * This file is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9  
10 #include <string.h>
11 #include <avr/pgmspace.h>
12 #include <avr/sleep.h>
13 #include "fat16.h"
14 #include "fat16_config.h"
15 #include "partition.h"
16 #include "sd_raw.h"
17 #include "sd_raw_config.h"
18 #include "uart.h"
19  
20 #define DEBUG 1
21  
22  
23 static uint8_t read_line(char* buffer, uint8_t buffer_length);
24 static uint32_t strtolong(const char* str);
25 static uint8_t find_file_in_dir(struct fat16_fs_struct* fs, struct fat16_dir_struct* dd, const char* name, struct fat16_dir_entry_struct* dir_entry);
26 static struct fat16_file_struct* open_file_in_dir(struct fat16_fs_struct* fs, struct fat16_dir_struct* dd, const char* name);
27 static uint8_t print_disk_info(const struct fat16_fs_struct* fs);
28  
29 int main()
30 {
31 /* we will just use ordinary idle mode */
32 set_sleep_mode(SLEEP_MODE_IDLE);
33  
34 /* setup uart */
35 uart_init();
36  
37 /* setup sd card slot */
38 if(!sd_raw_init())
39 {
40 #if DEBUG
41 uart_puts_p(PSTR("MMC/SD initialization failed\n"));
42 #endif
43 return 1;
44 }
45  
46 /* open first partition */
47 struct partition_struct* partition = partition_open(sd_raw_read,
48 sd_raw_read_interval,
49 sd_raw_write,
50 sd_raw_write_interval,
51  
52 );
53  
54 if(!partition)
55 {
56 /* If the partition did not open, assume the storage device
57 * is a "superfloppy", i.e. has no MBR.
58 */
59 partition = partition_open(sd_raw_read,
60 sd_raw_read_interval,
61 sd_raw_write,
62 sd_raw_write_interval,
63 -1
64 );
65 if(!partition)
66 {
67 #if DEBUG
68 uart_puts_p(PSTR("opening partition failed\n"));
69 #endif
70 return 1;
71 }
72 }
73  
74 /* open file system */
75 struct fat16_fs_struct* fs = fat16_open(partition);
76 if(!fs)
77 {
78 #if DEBUG
79 uart_puts_p(PSTR("opening filesystem failed\n"));
80 #endif
81 return 1;
82 }
83  
84 /* open root directory */
85 struct fat16_dir_entry_struct directory;
86 fat16_get_dir_entry_of_path(fs, "/", &directory);
87  
88 struct fat16_dir_struct* dd = fat16_open_dir(fs, &directory);
89 if(!dd)
90 {
91 #if DEBUG
92 uart_puts_p(PSTR("opening root directory failed\n"));
93 #endif
94 return 1;
95 }
96  
97 /* print some card information as a boot message */
98 print_disk_info(fs);
99  
100 /* provide a simple shell */
101 char buffer[20];
102 char* command = buffer;
103  
104 //!!!KAKL
105 {
106 uint8_t n;
107  
108 while(uart_getc()!='$');
109 while(uart_getc()!=',');
110 for(n=0; n<6; n++)
111 {
112 buffer[n]=uart_getc();
113 };
114 buffer[6]='\0';
115 }
116  
117 {
118 struct fat16_dir_entry_struct file_entry;
119 fat16_create_file(dd, command, &file_entry);
120 }
121  
122 {
123 int32_t offset;
124  
125 offset = 0;
126 while(1)
127 {
128 uint8_t znak;
129  
130 struct fat16_file_struct* fd = open_file_in_dir(fs, dd, command);
131 fat16_seek_file(fd, &offset, FAT16_SEEK_SET);
132 do
133 {
134 znak=uart_getc();
135 fat16_write_file(fd, (uint8_t*) &znak, 1);
136 uart_putc(znak);
137 offset++;
138 } while ((znak!='\n')&&(znak!='@'));
139  
140 fat16_close_file(fd);
141  
142 if(znak=='@') break;
143 }
144 }
145  
146 while(1)
147 {
148 /* print prompt */
149 uart_putc('>');
150 uart_putc(' ');
151  
152 /* read command */
153 if(read_line(command, sizeof(buffer)) < 1)
154 continue;
155  
156 /* execute command */
157 if(strncmp_P(command, PSTR("cd "), 3) == 0)
158 {
159 command += 3;
160 if(command[0] == '\0')
161 continue;
162  
163 /* change directory */
164 struct fat16_dir_entry_struct subdir_entry;
165 if(find_file_in_dir(fs, dd, command, &subdir_entry))
166 {
167 struct fat16_dir_struct* dd_new = fat16_open_dir(fs, &subdir_entry);
168 if(dd_new)
169 {
170 fat16_close_dir(dd);
171 dd = dd_new;
172 continue;
173 }
174 }
175  
176 uart_puts_p(PSTR("directory not found: "));
177 uart_puts(command);
178 uart_putc('\n');
179 }
180 else if(strcmp_P(command, PSTR("ls")) == 0)
181 {
182 /* print directory listing */
183 struct fat16_dir_entry_struct dir_entry;
184 while(fat16_read_dir(dd, &dir_entry))
185 {
186 uint8_t spaces = sizeof(dir_entry.long_name) - strlen(dir_entry.long_name) + 4;
187  
188 uart_puts(dir_entry.long_name);
189 uart_putc(dir_entry.attributes & FAT16_ATTRIB_DIR ? '/' : ' ');
190 while(spaces--)
191 uart_putc(' ');
192 uart_putdw_dec(dir_entry.file_size);
193 uart_putc('\n');
194 }
195 }
196 else if(strncmp_P(command, PSTR("cat "), 4) == 0)
197 {
198 command += 4;
199 if(command[0] == '\0')
200 continue;
201  
202 /* search file in current directory and open it */
203 struct fat16_file_struct* fd = open_file_in_dir(fs, dd, command);
204 if(!fd)
205 {
206 uart_puts_p(PSTR("error opening "));
207 uart_puts(command);
208 uart_putc('\n');
209 continue;
210 }
211  
212 /* print file contents */
213 uint8_t buffer[8];
214 uint32_t offset = 0;
215 while(fat16_read_file(fd, buffer, sizeof(buffer)) > 0)
216 {
217 uart_putdw_hex(offset);
218 uart_putc(':');
219 for(uint8_t i = 0; i < 8; ++i)
220 {
221 uart_putc(' ');
222 uart_putc_hex(buffer[i]);
223 }
224 uart_putc('\n');
225 offset += 8;
226 }
227  
228 fat16_close_file(fd);
229 }
230 else if(strcmp_P(command, PSTR("disk")) == 0)
231 {
232 if(!print_disk_info(fs))
233 uart_puts_p(PSTR("error reading disk info\n"));
234 }
235 #if FAT16_WRITE_SUPPORT
236 else if(strncmp_P(command, PSTR("rm "), 3) == 0)
237 {
238 command += 3;
239 if(command[0] == '\0')
240 continue;
241  
242 struct fat16_dir_entry_struct file_entry;
243 if(find_file_in_dir(fs, dd, command, &file_entry))
244 {
245 if(fat16_delete_file(fs, &file_entry))
246 continue;
247 }
248  
249 uart_puts_p(PSTR("error deleting file: "));
250 uart_puts(command);
251 uart_putc('\n');
252 }
253 else if(strncmp_P(command, PSTR("touch "), 6) == 0)
254 {
255 command += 6;
256 if(command[0] == '\0')
257 continue;
258  
259 struct fat16_dir_entry_struct file_entry;
260 if(!fat16_create_file(dd, command, &file_entry))
261 {
262 uart_puts_p(PSTR("error creating file: "));
263 uart_puts(command);
264 uart_putc('\n');
265 }
266 }
267 else if(strncmp_P(command, PSTR("write "), 6) == 0)
268 {
269 command += 6;
270 if(command[0] == '\0')
271 continue;
272  
273 char* offset_value = command;
274 while(*offset_value != ' ' && *offset_value != '\0')
275 ++offset_value;
276  
277 if(*offset_value == ' ')
278 *offset_value++ = '\0';
279 else
280 continue;
281  
282 /* search file in current directory and open it */
283 struct fat16_file_struct* fd = open_file_in_dir(fs, dd, command);
284 if(!fd)
285 {
286 uart_puts_p(PSTR("error opening "));
287 uart_puts(command);
288 uart_putc('\n');
289 continue;
290 }
291  
292 int32_t offset = strtolong(offset_value);
293 if(!fat16_seek_file(fd, &offset, FAT16_SEEK_SET))
294 {
295 uart_puts_p(PSTR("error seeking on "));
296 uart_puts(command);
297 uart_putc('\n');
298  
299 fat16_close_file(fd);
300 continue;
301 }
302  
303 /* read text from the shell and write it to the file */
304 uint8_t data_len;
305 while(1)
306 {
307 /* give a different prompt */
308 uart_putc('<');
309 uart_putc(' ');
310  
311 /* read one line of text */
312 data_len = read_line(buffer, sizeof(buffer));
313 if(!data_len)
314 break;
315  
316 /* write text to file */
317 if(fat16_write_file(fd, (uint8_t*) buffer, data_len) != data_len)
318 {
319 uart_puts_p(PSTR("error writing to file\n"));
320 break;
321 }
322 }
323  
324 fat16_close_file(fd);
325 }
326 else if(strncmp_P(command, PSTR("mkdir "), 6) == 0)
327 {
328 command += 6;
329 if(command[0] == '\0')
330 continue;
331  
332 struct fat16_dir_entry_struct dir_entry;
333 if(!fat16_create_dir(dd, command, &dir_entry))
334 {
335 uart_puts_p(PSTR("error creating directory: "));
336 uart_puts(command);
337 uart_putc('\n');
338 }
339 }
340 #endif
341 #if SD_RAW_WRITE_BUFFERING
342 else if(strcmp_P(command, PSTR("sync")) == 0)
343 {
344 if(!sd_raw_sync())
345 uart_puts_p(PSTR("error syncing disk\n"));
346 }
347 #endif
348 else
349 {
350 uart_puts_p(PSTR("unknown command: "));
351 uart_puts(command);
352 uart_putc('\n');
353 }
354 }
355  
356 /* close file system */
357 fat16_close(fs);
358  
359 /* close partition */
360 partition_close(partition);
361  
362 return 0;
363 }
364  
365 uint8_t read_line(char* buffer, uint8_t buffer_length)
366 {
367 memset(buffer, 0, buffer_length);
368  
369 uint8_t read_length = 0;
370 while(read_length < buffer_length - 1)
371 {
372 uint8_t c = uart_getc();
373  
374 if(c == 0x08 || c == 0x7f)
375 {
376 if(read_length < 1)
377 continue;
378  
379 --read_length;
380 buffer[read_length] = '\0';
381  
382 uart_putc(0x08);
383 uart_putc(' ');
384 uart_putc(0x08);
385  
386 continue;
387 }
388  
389 uart_putc(c);
390  
391 if(c == '\n')
392 {
393 buffer[read_length] = '\0';
394 break;
395 }
396 else
397 {
398 buffer[read_length] = c;
399 ++read_length;
400 }
401 }
402  
403 return read_length;
404 }
405  
406 uint32_t strtolong(const char* str)
407 {
408 uint32_t l = 0;
409 while(*str >= '0' && *str <= '9')
410 l = l * 10 + (*str++ - '0');
411  
412 return l;
413 }
414  
415 uint8_t find_file_in_dir(struct fat16_fs_struct* fs, struct fat16_dir_struct* dd, const char* name, struct fat16_dir_entry_struct* dir_entry)
416 {
417 while(fat16_read_dir(dd, dir_entry))
418 {
419 if(strcmp(dir_entry->long_name, name) == 0)
420 {
421 fat16_reset_dir(dd);
422 return 1;
423 }
424 }
425  
426 return 0;
427 }
428  
429 struct fat16_file_struct* open_file_in_dir(struct fat16_fs_struct* fs, struct fat16_dir_struct* dd, const char* name)
430 {
431 struct fat16_dir_entry_struct file_entry;
432 if(!find_file_in_dir(fs, dd, name, &file_entry))
433 return 0;
434  
435 return fat16_open_file(fs, &file_entry);
436 }
437  
438 uint8_t print_disk_info(const struct fat16_fs_struct* fs)
439 {
440 if(!fs)
441 return 0;
442  
443 struct sd_raw_info disk_info;
444 if(!sd_raw_get_info(&disk_info))
445 return 0;
446  
447 uart_puts_p(PSTR("manuf: 0x")); uart_putc_hex(disk_info.manufacturer); uart_putc('\n');
448 uart_puts_p(PSTR("oem: ")); uart_puts((char*) disk_info.oem); uart_putc('\n');
449 uart_puts_p(PSTR("prod: ")); uart_puts((char*) disk_info.product); uart_putc('\n');
450 uart_puts_p(PSTR("rev: ")); uart_putc_hex(disk_info.revision); uart_putc('\n');
451 uart_puts_p(PSTR("serial: 0x")); uart_putdw_hex(disk_info.serial); uart_putc('\n');
452 uart_puts_p(PSTR("date: ")); uart_putw_dec(disk_info.manufacturing_month); uart_putc('/');
453 uart_putw_dec(disk_info.manufacturing_year); uart_putc('\n');
454 uart_puts_p(PSTR("size: ")); uart_putdw_dec(disk_info.capacity); uart_putc('\n');
455 uart_puts_p(PSTR("copy: ")); uart_putw_dec(disk_info.flag_copy); uart_putc('\n');
456 uart_puts_p(PSTR("wr.pr.: ")); uart_putw_dec(disk_info.flag_write_protect_temp); uart_putc('/');
457 uart_putw_dec(disk_info.flag_write_protect); uart_putc('\n');
458 uart_puts_p(PSTR("format: ")); uart_putw_dec(disk_info.format); uart_putc('\n');
459 uart_puts_p(PSTR("free: ")); uart_putdw_dec(fat16_get_fs_free(fs)); uart_putc('/');
460 uart_putdw_dec(fat16_get_fs_size(fs)); uart_putc('\n');
461  
462 return 1;
463 }
464  
465 void get_datetime(uint16_t* year, uint8_t* month, uint8_t* day, uint8_t* hour, uint8_t* min, uint8_t* sec)
466 {
467 *year = 2007;
468 *month = 1;
469 *day = 1;
470 *hour = 0;
471 *min = 0;
472 *sec = 0;
473 }
474  
475