197d5da5cee8146f59633c34e217dc3f054a035b
[libam7xxx.git] / picoproj.c
1 /* picoproj - communication with AM7xxx based USB pico projectors
2  *
3  * Copyright (C) 2011  Antonio Ospite <ospite@studenti.unina.it>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include <endian.h>
24 #include <errno.h>
25 #include <unistd.h>
26
27 typedef enum {
28         AM7x01_PACKET_TYPE_INIT    = 0x01,
29         AM7x01_PACKET_TYPE_IMAGE   = 0x02,
30         AM7x01_PACKET_TYPE_POWER   = 0x04,
31         AM7x01_PACKET_TYPE_UNKNOWN = 0x05,
32 } am7x01_packet_type;
33
34 typedef enum {
35         AM7x01_IMAGE_FORMAT_JPEG = 1,
36 } am7x01_image_format;
37
38 typedef enum {
39         AM7x01_POWER_OFF  = 0,
40         AM7x01_POWER_LOW  = 1,
41         AM7x01_POWER_MID  = 2,
42         AM7x01_POWER_HIGH = 3,
43 } am7x01_power_mode;
44
45 struct image_header {
46         uint32_t format;
47         uint32_t width;
48         uint32_t height;
49         uint32_t image_size;
50 };
51
52 struct power_header {
53         uint32_t power_low;
54         uint32_t power_mid;
55         uint32_t power_high;
56 };
57
58 /*
59  * Examples of packet headers:
60  *
61  * Image widget:
62  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
63  * +02|00|00|00|00|10|3e|10|01|00|00|00|20|03|00|00|e0|01|00|00|53|E8|00|00+
64  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
65  *
66  * Brightness widget:
67  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
68  * +04|00|00|00|00|0c|ff|ff|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00+
69  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
70  */
71
72 static uint8_t reference_image_header[] = {
73         0x02, 0x00, 0x00, 0x00,
74         0x00,
75         0x10,
76         0x3e,
77         0x10,
78         0x01, 0x00, 0x00, 0x00,
79         0x20, 0x03, 0x00, 0x00,
80         0xe0, 0x01, 0x00, 0x00,
81         0x53, 0xE8, 0x00, 0x00
82 };
83
84 struct header {
85         uint32_t packet_type;
86         uint8_t unknown0;
87         uint8_t header_len;
88         uint8_t unknown2;
89         uint8_t unknown3;
90         union {
91                 struct image_header image;
92                 struct power_header power;
93         } header_data;
94 };
95
96
97 static void dump_image_header(struct image_header *i)
98 {
99         if (i == NULL)
100                 return;
101
102         printf("Image header:\n");
103         printf("format:      0x%08x (%u)\n", i->format, i->format);
104         printf("width:       0x%08x (%u)\n", i->width, i->width);
105         printf("height:      0x%08x (%u)\n", i->height, i->height);
106         printf("image size:  0x%08x (%u)\n", i->image_size, i->image_size);
107 }
108
109 static void dump_header(struct header *h)
110 {
111         if (h == NULL)
112                 return;
113
114         printf("packet_type: 0x%08x (%u)\n", h->packet_type, h->packet_type);
115         printf("unknown0:    0x%02hhx (%hhu)\n", h->unknown0, h->unknown0);
116         printf("header_len:  0x%02hhx (%hhu)\n", h->header_len, h->header_len);
117         printf("unknown2:    0x%02hhx (%hhu)\n", h->unknown2, h->unknown2);
118         printf("unknown3:    0x%02hhx (%hhu)\n", h->unknown3, h->unknown3);
119
120         switch(h->packet_type) {
121         case AM7x01_PACKET_TYPE_IMAGE:
122                 dump_image_header(&(h->header_data.image));
123                 break;
124
125         default:
126                 printf("Packet type not supported!\n");
127                 break;
128         }
129
130         fflush(stdout);
131 }
132
133 static void dump_buffer(uint8_t *buffer, unsigned int len)
134 {
135         unsigned int i;
136
137         if (buffer == NULL || len == 0)
138                 return;
139
140         for (i = 0; i < len; i++) {
141                 printf("%02hhX%c", buffer[i], (i < len - 1) ? ' ' : '\n');
142         }
143         fflush(stdout);
144 }
145
146 static int send_data(uint8_t *buffer, unsigned int len)
147 {
148         dump_buffer(buffer, len);
149         return 0;
150 }
151
152 static int send_header(struct header *h)
153 {
154         union {
155                 struct header header;
156                 uint8_t buffer[sizeof (struct header)];
157         } data;
158
159         data.header = *h;
160
161         return send_data(data.buffer, sizeof (struct header));
162 }
163
164 static int send_image(am7x01_image_format format,
165                       unsigned int width,
166                       unsigned int height,
167                       uint8_t *image,
168                       unsigned int size)
169 {
170         int ret;
171         struct header h = {
172                 .packet_type = htole32(AM7x01_PACKET_TYPE_IMAGE),
173                 .unknown0    = 0x00,
174                 .header_len  = sizeof(struct image_header),
175                 .unknown2    = 0x3e,
176                 .unknown3    = 0x10,
177                 .header_data = {
178                         .image = {
179                                 .format     = htole32(format),
180                                 .width      = htole32(width),
181                                 .height     = htole32(height),
182                                 .image_size = htole32(size),
183                         },
184                 },
185         };
186
187         dump_header(&h);
188         printf("\n");
189
190         printf("Dump Buffers\n");
191         dump_buffer(reference_image_header, sizeof(struct header));
192
193         ret = send_header(&h);
194         if (ret < 0)
195                 return ret;
196
197         if (image == NULL || size == 0)
198                 return 0;
199
200         return send_data(image, size);
201 }
202
203 static void usage(char *name)
204 {
205         printf("usage: %s [OPTIONS]\n\n", name);
206         printf("OPTIONS:\n");
207         printf("\t-f <filename>\t\tthe image file to upload\n");
208         printf("\t-F <format>\t\tthe image format to use (default is JPEG).\n");
209         printf("\t\t\t\tSUPPORTED FORMATS:\n");
210         printf("\t\t\t\t\t1 - JPEG\n");
211         printf("\t-W <image width>\tthe width of the image to upload\n");
212         printf("\t-H <image height>\tthe height of the image to upload\n");
213         printf("\t-h \t\t\tthis help message\n");
214 }
215
216 int main(int argc, char *argv[])
217 {
218         int ret;
219         int opt;
220
221         char filename[FILENAME_MAX] = {0};
222         int format = AM7x01_IMAGE_FORMAT_JPEG;
223         int width = 800;
224         int height = 480;
225         uint8_t *image = NULL;
226         int size = 59475;
227
228         while ((opt = getopt(argc, argv, "f:F:W:H:h")) != -1) {
229                 switch (opt) {
230                 case 'f':
231                         strncpy(filename, optarg, FILENAME_MAX);
232                         break;
233                 case 'F':
234                         format = atoi(optarg);
235                         if (format != 1) {
236                                 fprintf(stderr, "Unsupported format\n");
237                                 exit(EXIT_FAILURE);
238                         }
239                         break;
240                 case 'W':
241                         width = atoi(optarg);
242                         if (width < 0) {
243                                 fprintf(stderr, "Unsupported width\n");
244                                 exit(EXIT_FAILURE);
245                         }
246                         break;
247                 case 'H':
248                         height = atoi(optarg);
249                         if (height < 0) {
250                                 fprintf(stderr, "Unsupported height\n");
251                                 exit(EXIT_FAILURE);
252                         }
253                         break;
254                 default: /* '?' */
255                         usage(argv[0]);
256                         exit(EXIT_FAILURE);
257                 }
258         }
259
260         ret = send_image(format, width, height, image, size);
261         if (ret < 0) {
262                 perror("send_image");
263                 exit(EXIT_FAILURE);
264         }
265
266         exit(EXIT_SUCCESS);
267 }