From: Antonio Ospite <ospite@studenti.unina.it>
Date: Wed, 25 Jan 2012 14:26:44 +0000 (+0100)
Subject: Implement am7xxx_get_device_info()
X-Git-Tag: v0.1.0~11
X-Git-Url: https://git.ao2.it/libam7xxx.git/commitdiff_plain/48aab112af60be0f18c0e6fbf1534415af445a8f?ds=sidebyside;hp=--cc

Implement am7xxx_get_device_info()

Add support for packet type 0x01, which can be used to query device
information like the native width and native height.

Introduce also read_data(), read_header(), unserialize_header()
which are needed by am7xxx_get_device_info()
---

48aab112af60be0f18c0e6fbf1534415af445a8f
diff --git a/src/am7xxx.c b/src/am7xxx.c
index 90dcc8c..cdcbf3f 100644
--- a/src/am7xxx.c
+++ b/src/am7xxx.c
@@ -26,6 +26,18 @@
 #define AM7XXX_VENDOR_ID  0x1de1
 #define AM7XXX_PRODUCT_ID 0xc101
 
+static void dump_devinfo_header(struct am7xxx_devinfo_header *d)
+{
+	if (d == NULL)
+		return;
+
+	printf("Info header:\n");
+	printf("\tnative_width:  0x%08x (%u)\n", d->native_width, d->native_width);
+	printf("\tnative_height: 0x%08x (%u)\n", d->native_height, d->native_height);
+	printf("\tunknown0:      0x%08x (%u)\n", d->unknown0, d->unknown0);
+	printf("\tunknown1:      0x%08x (%u)\n", d->unknown1, d->unknown1);
+}
+
 static void dump_image_header(struct am7xxx_image_header *i)
 {
 	if (i == NULL)
@@ -61,6 +73,10 @@ static void dump_header(struct am7xxx_header *h)
 	printf("unknown3:        0x%02hhx (%hhu)\n", h->unknown3, h->unknown3);
 
 	switch(h->packet_type) {
+	case AM7XXX_PACKET_TYPE_DEVINFO:
+		dump_devinfo_header(&(h->header_data.devinfo));
+		break;
+
 	case AM7XXX_PACKET_TYPE_IMAGE:
 		dump_image_header(&(h->header_data.image));
 		break;
@@ -97,6 +113,27 @@ static void dump_buffer(uint8_t *buffer, unsigned int len)
 	fflush(stdout);
 }
 
+static int read_data(am7xxx_device dev, uint8_t *buffer, unsigned int len)
+{
+	int ret;
+	int transferred;
+
+	ret = libusb_bulk_transfer(dev, 0x81, buffer, len, &transferred, 0);
+	if (ret != 0 || (unsigned int)transferred != len) {
+		fprintf(stderr, "Error: ret: %d\ttransferred: %d (expected %u)\n",
+			ret, transferred, len);
+		return ret;
+	}
+
+#if DEBUG
+	printf("\n<-- received\n");
+	dump_buffer(buffer, len);
+	printf("\n");
+#endif
+
+	return 0;
+}
+
 static int send_data(am7xxx_device dev, uint8_t *buffer, unsigned int len)
 {
 	int ret;
@@ -133,6 +170,51 @@ static void serialize_header(struct am7xxx_header *h, uint8_t *buffer)
 	put_le32(h->header_data.data.field3, buffer_iterator);
 }
 
+static void unserialize_header(uint8_t *buffer, struct am7xxx_header *h)
+{
+	uint8_t **buffer_iterator = &buffer;
+
+	h->packet_type = get_le32(buffer_iterator);
+	h->unknown0 = get_8(buffer_iterator);
+	h->header_data_len = get_8(buffer_iterator);
+	h->unknown2 = get_8(buffer_iterator);
+	h->unknown3 = get_8(buffer_iterator);
+	h->header_data.data.field0 = get_le32(buffer_iterator);
+	h->header_data.data.field1 = get_le32(buffer_iterator);
+	h->header_data.data.field2 = get_le32(buffer_iterator);
+	h->header_data.data.field3 = get_le32(buffer_iterator);
+}
+
+static int read_header(am7xxx_device dev, struct am7xxx_header *h)
+{
+	uint8_t *buffer;
+	int ret;
+
+	buffer = calloc(AM7XXX_HEADER_WIRE_SIZE, 1);
+	if (buffer == NULL) {
+		perror("calloc buffer");
+		return -ENOMEM;
+	}
+
+	ret = read_data(dev, buffer, AM7XXX_HEADER_WIRE_SIZE);
+	if (ret < 0)
+		goto out;
+
+	unserialize_header(buffer, h);
+
+#if DEBUG
+	printf("\n");
+	dump_header(h);
+	printf("\n");
+#endif
+
+	ret = 0;
+
+out:
+	free(buffer);
+	return ret;
+}
+
 static int send_header(am7xxx_device dev, struct am7xxx_header *h)
 {
 	uint8_t *buffer;
@@ -193,6 +275,45 @@ void am7xxx_shutdown(am7xxx_device dev)
 	}
 }
 
+int am7xxx_get_device_info(am7xxx_device dev,
+			   unsigned int *native_width,
+			   unsigned int *native_height,
+			   unsigned int *unknown0,
+			   unsigned int *unknown1)
+{
+	int ret;
+	struct am7xxx_header h = {
+		.packet_type     = AM7XXX_PACKET_TYPE_DEVINFO,
+		.unknown0        = 0x00,
+		.header_data_len = 0x00,
+		.unknown2        = 0x3e,
+		.unknown3        = 0x10,
+		.header_data = {
+			.devinfo = {
+				.native_width  = 0,
+				.native_height = 0,
+				.unknown0      = 0,
+				.unknown1      = 0,
+			},
+		},
+	};
+
+	ret = send_header(dev, &h);
+	if (ret < 0)
+		return ret;
+
+	ret = read_header(dev, &h);
+	if (ret < 0)
+		return ret;
+
+	*native_width = h.header_data.devinfo.native_width;
+	*native_height = h.header_data.devinfo.native_height;
+	*unknown0 = h.header_data.devinfo.unknown0;
+	*unknown1 = h.header_data.devinfo.unknown1;
+
+	return 0;
+}
+
 int am7xxx_send_image(am7xxx_device dev,
 		      am7xxx_image_format format,
 		      unsigned int width,
diff --git a/src/am7xxx.h b/src/am7xxx.h
index 6847796..393c53f 100644
--- a/src/am7xxx.h
+++ b/src/am7xxx.h
@@ -29,7 +29,7 @@ extern "C" {
 typedef libusb_device_handle *am7xxx_device;
 
 typedef enum {
-	AM7XXX_PACKET_TYPE_INIT	   = 0x01,
+	AM7XXX_PACKET_TYPE_DEVINFO = 0x01,
 	AM7XXX_PACKET_TYPE_IMAGE   = 0x02,
 	AM7XXX_PACKET_TYPE_POWER   = 0x04,
 	AM7XXX_PACKET_TYPE_UNKNOWN = 0x05,
@@ -55,6 +55,13 @@ struct am7xxx_generic_header {
 	uint32_t field3;
 };
 
+struct am7xxx_devinfo_header {
+	uint32_t native_width;
+	uint32_t native_height;
+	uint32_t unknown0;
+	uint32_t unknown1;
+};
+
 struct am7xxx_image_header {
 	uint32_t format;
 	uint32_t width;
@@ -92,6 +99,7 @@ struct am7xxx_header {
 	uint8_t unknown3;
 	union {
 		struct am7xxx_generic_header data;
+		struct am7xxx_devinfo_header devinfo;
 		struct am7xxx_image_header image;
 		struct am7xxx_power_header power;
 	} header_data;
@@ -101,6 +109,12 @@ am7xxx_device am7xxx_init(void);
 
 void am7xxx_shutdown(am7xxx_device dev);
 
+int am7xxx_get_device_info(am7xxx_device dev,
+			   unsigned int *native_width,
+			   unsigned int *native_height,
+			   unsigned int *unknown0,
+			   unsigned int *unknown1);
+
 int am7xxx_send_image(am7xxx_device dev,
 		      am7xxx_image_format format,
 		      unsigned int width,
diff --git a/src/picoproj.c b/src/picoproj.c
index 1aa6b04..8d511b9 100644
--- a/src/picoproj.c
+++ b/src/picoproj.c
@@ -56,6 +56,10 @@ int main(int argc, char *argv[])
 	int height = 480;
 	uint8_t *image;
 	unsigned int size;
+	unsigned int native_width;
+	unsigned int native_height;
+	unsigned int unknown0;
+	unsigned int unknown1;
 
 	while ((opt = getopt(argc, argv, "f:F:W:H:h")) != -1) {
 		switch (opt) {
@@ -133,6 +137,16 @@ int main(int argc, char *argv[])
 		goto out_munmap;
 	}
 
+	ret = am7xxx_get_device_info(dev, &native_width, &native_height, &unknown0, &unknown1);
+	if (ret < 0) {
+		perror("am7xxx_get_info");
+		exit_code = EXIT_FAILURE;
+		goto cleanup;
+	}
+	printf("Native resolution: %dx%d\n", native_width, native_height);
+	printf("Unknown0: %d\n", unknown0);
+	printf("Unknown1: %d\n", unknown1);
+
 	ret = am7xxx_set_power_mode(dev, AM7XXX_POWER_LOW);
 	if (ret < 0) {
 		perror("am7xxx_set_power_mode");