/* picoproj - communication with AM7xxx based USB pico projectors * * Copyright (C) 2011 Antonio Ospite * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include /* * Examples of packet headers: * * Image widget: * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * +02|00|00|00|00|10|3e|10|01|00|00|00|20|03|00|00|e0|01|00|00|53|E8|00|00+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * * Brightness widget: * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * +04|00|00|00|00|0c|ff|ff|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #define AM7x01_PACKET_TYPE_INIT 0x01 #define AM7x01_PACKET_TYPE_IMAGE 0x02 #define AM7x01_PACKET_TYPE_POWER 0x04 #define AM7x01_PACKET_TYPE_UNKNOWN 0x05 struct buffer { unsigned int len; uint8_t *data; }; struct header{ uint32_t packet_type; uint32_t unknown1; uint32_t unknown2; uint32_t width; uint32_t height; uint32_t payload_size; }; struct packet { struct header header; uint8_t payload[]; }; static struct buffer *packet_allocate_buffer(struct packet *p) { struct buffer *buffer; if (p == NULL) { perror("packet NULL"); return NULL; } buffer = malloc(sizeof(*buffer)); if (buffer == NULL) { perror("malloc buffer"); return NULL; } buffer->len = sizeof(p->header); /* + p->header.payload_size; */ buffer->data = malloc(buffer->len); if (buffer->data == NULL) { perror("malloc buffer->data"); free(buffer); return NULL; } return buffer; } static void packet_free_buffer(struct buffer *buffer) { free(buffer->data); free(buffer); buffer = NULL; } static int packet_pack(struct packet *p, struct buffer *buffer) { unsigned int offset; uint32_t tmp; if (p == NULL || buffer == NULL) return -EINVAL; /* TODO: check for packet payload being NULL? */ if (buffer->data == NULL || buffer->len < sizeof(*p)) return -EINVAL; offset = 0; tmp = htole32(p->header.packet_type); memcpy(buffer->data + offset, &tmp, sizeof(p->header.packet_type)); offset += sizeof(p->header.packet_type); tmp = htole32(p->header.unknown1); memcpy(buffer->data + offset, &tmp, sizeof(p->header.unknown1)); offset += sizeof(p->header.unknown1); tmp = htole32(p->header.unknown2); memcpy(buffer->data + offset, &tmp, sizeof(p->header.unknown2)); offset += sizeof(p->header.unknown2); tmp = htole32(p->header.width); memcpy(buffer->data + offset, &tmp, sizeof(p->header.width)); offset += sizeof(p->header.width); tmp = htole32(p->header.height); memcpy(buffer->data + offset, &tmp, sizeof(p->header.height)); offset += sizeof(p->header.height); tmp = htole32(p->header.payload_size); memcpy(buffer->data + offset, &tmp, sizeof(p->header.payload_size)); offset += sizeof(p->header.payload_size); /* TODO memcpy payload of size */ return 0; } static int packet_unpack(struct buffer *buffer, struct packet *p) { unsigned int offset; uint32_t tmp; if (p == NULL || buffer == NULL) return -EINVAL; /* TODO: check for packet payload being NULL? */ if (buffer->data == NULL || buffer->len < sizeof(*p)) return -EINVAL; offset = 0; memcpy(&tmp, buffer->data + offset, sizeof(p->header.packet_type)); p->header.packet_type = le32toh(tmp); offset += sizeof(p->header.packet_type); memcpy(&tmp, buffer->data + offset, sizeof(p->header.unknown1)); p->header.unknown1 = le32toh(tmp); offset += sizeof(p->header.unknown1); memcpy(&tmp, buffer->data + offset, sizeof(p->header.unknown2)); p->header.unknown2 = le32toh(tmp); offset += sizeof(p->header.unknown2); memcpy(&tmp, buffer->data + offset, sizeof(p->header.width)); p->header.width = le32toh(tmp); offset += sizeof(p->header.width); memcpy(&tmp, buffer->data + offset, sizeof(p->header.height)); p->header.height = le32toh(tmp); offset += sizeof(p->header.height); memcpy(&tmp, buffer->data + offset, sizeof(p->header.payload_size)); p->header.payload_size = le32toh(tmp); offset += sizeof(p->header.payload_size); /* malloc & memcpy payload of size p->header.payload_size */ return 0; } static void packet_dump_header(struct packet *p) { if (p == NULL) return; printf("packet_type: 0x%08x (%u)\n", p->header.packet_type, p->header.packet_type); printf("unknown1: 0x%08x (%u)\n", p->header.unknown1, p->header.unknown1); printf("unknown2: 0x%08x (%u)\n", p->header.unknown2, p->header.unknown2); printf("width: 0x%08x (%u)\n", p->header.width, p->header.width); printf("height: 0x%08x (%u)\n", p->header.height, p->header.height); printf("size: 0x%08x (%u)\n", p->header.payload_size, p->header.payload_size); fflush(stdout); } static void packet_dump_buffer(struct buffer *buffer) { unsigned int i; if (buffer == NULL) return; if (buffer->data == NULL) return; for (i = 0; i < buffer->len; i++) { printf("%02hhX%c", buffer->data[i], (i < buffer->len - 1) ? ' ' : '\n'); } fflush(stdout); } int main(void) { struct packet p1 = { .header = { .packet_type = AM7x01_PACKET_TYPE_IMAGE, .unknown1 = le32toh(0x103e1000), .unknown2 = le32toh(0x00000001), .width = 800, .height = 480, .payload_size = 59475, }, /* TODO initialize payload */ }; struct buffer *buffer = NULL; struct packet p2; int ret; packet_dump_header(&p1); buffer = packet_allocate_buffer(&p1); if (buffer == NULL) { fprintf(stderr, "Cannot allocate the buffer.\n"); exit(EXIT_FAILURE); } ret = packet_pack(&p1, buffer); if (ret < 0) { fprintf(stderr, "Cannot pack the packet.\n"); exit(EXIT_FAILURE); } packet_dump_buffer(buffer); ret = packet_unpack(buffer, &p2); if (ret < 0) { fprintf(stderr, "Cannot unpack the packet.\n"); exit(EXIT_FAILURE); } packet_dump_header(&p2); packet_free_buffer(buffer); exit(EXIT_SUCCESS); }