ajout d'un exemple de systeme d'autoconfiguration via http
[ipphone-tools.git] / ipphone5-download.c
1 #include <sys/socket.h>
2 #include <netinet/in.h>
3 #include <arpa/inet.h> /* inet_aton,inet_ntoa */
4 #include <unistd.h> /* read,write,close */
5 #include <string.h> /* memset */
6 #include <stdlib.h> /* malloc */
7 #include <stdio.h> /* FILE,fprintf */
8
9 #define FILE_READ_MAX_SIZE 655000
10 #define FILE_ONE_PAGE_SIZE 64000
11
12 #define SDRAM_MAX_LENGTH 640000
13 #define TOTAL_SETTINGS_SIZE 4096
14
15 #define TCP_DOWNLOAD_SIZE 128
16 #define TCP_DOWNLOAD_PORT 0x2223 // 8739
17
18 #define DATA_HINT "dh"
19 #define SETTINGS_HINT "sh"
20
21 /*
22 * Download protocol (from PalmToolDlg.cpp):
23 * Step1. PC make a TCP connection to Palm1's page0 program
24 * Step2. PC sends 2 bytes to Palm1 for data "dh" or settings "sh" hints
25 * Palm1 sends back 128 byte of data
26 * Repeat step2 until the whole data has been received
27 * Step3. PC close the TCP connection indicate the download is over
28 */
29 int download(int sd, char *buffer, size_t length, const char *hint) {
30 fprintf(stdout, "Downloading... ");
31 // receiving data
32 while (length > 0) {
33 write(sd, hint, strlen(hint));
34 read(sd, buffer, TCP_DOWNLOAD_SIZE);
35 // FIXME: should check for errors!
36 fprintf(stdout, "%10d\b\b\b\b\b\b\b\b\b\b", length);
37 buffer += TCP_DOWNLOAD_SIZE;
38 length -= TCP_DOWNLOAD_SIZE;
39 }
40 fprintf(stdout, "Done. \n");
41 return 0;
42 }
43
44 int main(int argc, const char *argv[]) {
45 const char *progname, *filename, *extension, *hint, *ipaddr;
46 FILE *filehandle;
47 size_t length, length_padded;
48 char *buffer;
49 struct in_addr sin_addr;
50 int sd;
51 struct sockaddr_in sin;
52
53 // check arguments count
54 progname = argv[0];
55 if (argc != 3) {
56 fprintf(stderr, "Syntax: %s <filename> <IPv4-address>\n", progname);
57 return 1;
58 }
59 filename = argv[1];
60 ipaddr = argv[2];
61
62 // check first argument (filename)
63 filehandle = fopen(filename, "wb");
64 if (filehandle == NULL) {
65 fprintf(stderr, "Unable to open '%s' !\n", filename);
66 return 2;
67 }
68 fprintf(stdout, "File name: %s\n", filename);
69
70 // check file type (by extension, for now...)
71 extension = strrchr(filename, '.');
72 if (extension && !strcasecmp(extension, ".dh")) {
73 hint = DATA_HINT;
74 length = SDRAM_MAX_LENGTH; // < FILE_READ_MAX_SIZE
75 } else if (extension && !strcasecmp(extension, ".sh")) {
76 hint = SETTINGS_HINT;
77 length = TOTAL_SETTINGS_SIZE; // < FILE_ONE_PAGE_SIZE
78 } else {
79 fprintf(stderr, "Unknown file type!\n");
80 return 2;
81 }
82
83 // normalize file size
84 length_padded = length + TCP_DOWNLOAD_SIZE*2 - 1;
85 length_padded /= TCP_DOWNLOAD_SIZE*2;
86 length_padded *= TCP_DOWNLOAD_SIZE*2;
87
88 // prepare to load data into memory
89 fprintf(stdout, "File length: %d bytes", length);
90 if (length_padded > length) {
91 fprintf(stdout, " (padding to %d bytes)", length_padded);
92 }
93 fprintf(stdout, "\n");
94 buffer = malloc(length_padded);
95 if (buffer == NULL) {
96 fprintf(stderr, "Unable to allocate enough (%d bytes) memory!\n", length_padded);
97 return 4;
98 }
99
100 // check second argument (IPv4 address)
101 if (!inet_aton(ipaddr, &sin_addr)) {
102 fprintf(stderr, "'%s' is an invalid IPv4 address!\n", ipaddr);
103 return 6;
104 }
105 fprintf(stdout, "IPv4 address: %s\n", inet_ntoa(sin_addr));
106
107 // connect to the host
108 sd = socket(PF_INET, SOCK_STREAM, 0);
109 if (sd < 0) {
110 fprintf(stderr, "Unable to create a socket!\n");
111 return 7;
112 }
113 memset(&sin, 0, sizeof(sin));
114 sin.sin_family = AF_INET;
115 sin.sin_port = htons(TCP_DOWNLOAD_PORT);
116 memcpy(&sin.sin_addr, &sin_addr, sizeof(sin.sin_addr));
117 if (connect(sd, (struct sockaddr *)&sin, sizeof(sin))) {
118 fprintf(stderr, "Unable to connect to host!\n");
119 return 8;
120 }
121
122 // do the upgrade process
123 setbuf(stdout, NULL);
124 if (download(sd, buffer, length_padded, hint)) return 9;
125
126 // save to file
127 //if (length < length_padded) {
128 // memset(buffer + length, 0, length_padded - length);
129 //}
130 if (fwrite(buffer, length, 1, filehandle) != 1) { // XXX: length_padded?
131 fprintf(stderr, "Unable to write the whole file content!\n");
132 return 5;
133 }
134 fclose(filehandle);
135
136 // cleaning
137 close(sd);
138 return 0;
139 }