f1c6a3b64a861eef6509ceaed9035fa9163a24db
[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
26 /*
27  * Examples of a packet headers:
28  *
29  * Image widget:
30  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
31  * +02|00|00|00|00|10|3e|10|01|00|00|00|20|03|00|00|e0|01|00|00|53|E8|00|00+
32  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
33  *
34  * Brightness widget:
35  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36  * +04|00|00|00|00|0c|ff|ff|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00+
37  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38  */
39
40 #define AM7x01_PACKET_TYPE_INIT    0x01
41 #define AM7x01_PACKET_TYPE_IMAGE   0x02
42 #define AM7x01_PACKET_TYPE_POWER   0x04
43 #define AM7x01_PACKET_TYPE_UNKNOWN 0x05
44
45 struct buffer {
46         unsigned int len;
47         uint8_t *data;
48 };
49
50 struct header{
51         uint32_t packet_type;
52         uint32_t unknown1;
53         uint32_t unknown2;
54         uint32_t width;
55         uint32_t height;
56         uint32_t payload_size;
57 };
58
59 struct packet {
60         struct header header;
61         uint8_t payload[];
62 };
63
64 static struct buffer *packet_allocate_buffer(struct packet *p)
65 {
66         struct buffer *buffer;
67
68         if (p == NULL) {
69                 perror("packet NULL");
70                 return NULL;
71         }
72
73         buffer = malloc(sizeof(*buffer));
74         if (buffer == NULL) {
75                 perror("malloc buffer");
76                 return NULL;
77         }
78
79         buffer->len = sizeof(p->header); /* + p->header.payload_size; */
80
81         buffer->data = malloc(buffer->len);
82         if (buffer->data == NULL) {
83                 perror("malloc buffer->data");
84                 free(buffer);
85                 return NULL;
86         }
87         return buffer;
88 }
89
90 static void packet_free_buffer(struct buffer *buffer)
91 {
92         free(buffer->data);
93         free(buffer);
94         buffer = NULL;
95 }
96
97 static int packet_pack(struct packet *p, struct buffer *buffer)
98 {
99         unsigned int offset;
100         uint32_t tmp;
101
102         if (p == NULL || buffer == NULL)
103                 return -EINVAL;
104
105         /* TODO: check for packet payload being NULL? */
106         if (buffer->data == NULL || buffer->len < sizeof(*p))
107                 return -EINVAL;
108
109         offset = 0;
110
111         tmp = htole32(p->header.packet_type);
112         memcpy(buffer->data + offset, &tmp, sizeof(p->header.packet_type));
113         offset += sizeof(p->header.packet_type);
114
115         tmp = htole32(p->header.unknown1);
116         memcpy(buffer->data + offset, &tmp, sizeof(p->header.unknown1));
117         offset += sizeof(p->header.unknown1);
118
119         tmp = htole32(p->header.unknown2);
120         memcpy(buffer->data + offset, &tmp, sizeof(p->header.unknown2));
121         offset += sizeof(p->header.unknown2);
122
123         tmp = htole32(p->header.width);
124         memcpy(buffer->data + offset, &tmp, sizeof(p->header.width));
125         offset += sizeof(p->header.width);
126
127         tmp = htole32(p->header.height);
128         memcpy(buffer->data + offset, &tmp, sizeof(p->header.height));
129         offset += sizeof(p->header.height);
130
131         tmp = htole32(p->header.payload_size);
132         memcpy(buffer->data + offset, &tmp, sizeof(p->header.payload_size));
133         offset += sizeof(p->header.payload_size);
134
135         /* TODO memcpy payload of size */
136
137         return 0;
138 }
139
140 static int packet_unpack(struct buffer *buffer, struct packet *p)
141 {
142         unsigned int offset;
143         uint32_t tmp;
144
145         if (p == NULL || buffer == NULL)
146                 return -EINVAL;
147
148         /* TODO: check for packet payload being NULL? */
149         if (buffer->data == NULL || buffer->len < sizeof(*p))
150                 return -EINVAL;
151
152         offset = 0;
153
154         memcpy(&tmp, buffer->data + offset, sizeof(p->header.packet_type));
155         p->header.packet_type = le32toh(tmp);
156         offset += sizeof(p->header.packet_type);
157
158         memcpy(&tmp, buffer->data + offset, sizeof(p->header.unknown1));
159         p->header.unknown1 = le32toh(tmp);
160         offset += sizeof(p->header.unknown1);
161
162         memcpy(&tmp, buffer->data + offset, sizeof(p->header.unknown2));
163         p->header.unknown2 = le32toh(tmp);
164         offset += sizeof(p->header.unknown2);
165
166         memcpy(&tmp, buffer->data + offset, sizeof(p->header.width));
167         p->header.width = le32toh(tmp);
168         offset += sizeof(p->header.width);
169
170         memcpy(&tmp, buffer->data + offset, sizeof(p->header.height));
171         p->header.height = le32toh(tmp);
172         offset += sizeof(p->header.height);
173
174         memcpy(&tmp, buffer->data + offset, sizeof(p->header.payload_size));
175         p->header.payload_size = le32toh(tmp);
176         offset += sizeof(p->header.payload_size);
177
178         /* malloc & memcpy payload of size p->header.payload_size */
179
180         return 0;
181 }
182
183 static void packet_dump_header(struct packet *p)
184 {
185         if (p == NULL)
186                 return;
187
188         printf("packet_type: 0x%08x (%u)\n", p->header.packet_type, p->header.packet_type);
189         printf("unknown1:    0x%08x (%u)\n", p->header.unknown1, p->header.unknown1);
190         printf("unknown2:    0x%08x (%u)\n", p->header.unknown2, p->header.unknown2);
191         printf("width:       0x%08x (%u)\n", p->header.width, p->header.width);
192         printf("height:      0x%08x (%u)\n", p->header.height, p->header.height);
193         printf("size:        0x%08x (%u)\n", p->header.payload_size, p->header.payload_size);
194         fflush(stdout);
195 }
196
197 static void packet_dump_buffer(struct buffer *buffer)
198 {
199         unsigned int i;
200
201         if (buffer == NULL)
202                 return;
203
204         if (buffer->data == NULL)
205                 return;
206
207         for (i = 0; i < buffer->len; i++) {
208                 printf("%02hhX%c", buffer->data[i], (i < buffer->len - 1) ? ' ' : '\n');
209         }
210         fflush(stdout);
211 }
212
213 int main(void)
214 {
215         struct packet p1  = {
216                 .header = {
217                         .packet_type  = AM7x01_PACKET_TYPE_IMAGE,
218                         .unknown1     = le32toh(0x103e1000),
219                         .unknown2     = le32toh(0x00000001),
220                         .width        = 800,
221                         .height       = 480,
222                         .payload_size = 59475,
223                 },
224                 /* TODO initialize payload */
225         };
226         struct buffer *buffer = NULL;
227         struct packet p2;
228         int ret;
229
230         packet_dump_header(&p1);
231
232         buffer = packet_allocate_buffer(&p1);
233         if (buffer == NULL) {
234                 fprintf(stderr, "Cannot allocate the buffer.\n");
235                 exit(EXIT_FAILURE);
236         }
237
238         ret = packet_pack(&p1, buffer);
239         if (ret < 0) {
240                 fprintf(stderr, "Cannot pack the packet.\n");
241                 exit(EXIT_FAILURE);
242         }
243
244         packet_dump_buffer(buffer);
245
246         ret = packet_unpack(buffer, &p2);
247         if (ret < 0) {
248                 fprintf(stderr, "Cannot unpack the packet.\n");
249                 exit(EXIT_FAILURE);
250         }
251
252         packet_dump_header(&p2);
253
254         packet_free_buffer(buffer);
255
256         exit(EXIT_SUCCESS);
257 }