From 351bfbd055aae28cd545bf3513a80f266ce841a2 Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Tue, 18 Nov 2014 23:24:02 +0100 Subject: mkii: Implement device initialization --- src/mkii.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 119 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/mkii.c b/src/mkii.c index 81e860d..e51943b 100644 --- a/src/mkii.c +++ b/src/mkii.c @@ -17,25 +17,125 @@ */ +#include +#include +#include + +#include + #include "mkii.h" #include "global.h" #include "image.h" #include "device.h" #include "usb-device.h" +#define MKII_PING 0x00000000 +#define MKII_GET_PROTOCOL 0x01010000 +#define MKII_TELL_PROTOCOL 0x02020000 +#define MKII_GET_DEVICE 0x01030000 +#define MKII_GET_HWREV 0x01040000 +#define MKII_GET_IMAGES 0x01050000 +#define MKII_REBOOT 0x0C060000 +#define MKII_INIT_SEND 0x03010000 +#define MKII_SEND_IMAGE 0x04020000 + +struct mkii_message { + uint32_t header; + uint16_t size; + uint32_t type; + char data[]; +} __attribute__((__packed__)); + +static int mkii_send_receive(usb_dev_handle * udev, uint32_t type, struct mkii_message * in_msg, size_t data_size, struct mkii_message * out_msg, size_t out_size) { + + int ret; + + in_msg->header = 0x8810001B; + in_msg->size = htons(data_size + 4); + in_msg->type = type; + + ret = usb_bulk_write(udev, 1, (const char *)in_msg, data_size + sizeof(*in_msg), 5000); + if ( ret < 0 ) + return ret; + if ( (size_t)ret != data_size + sizeof(*in_msg) ) + return -1; + + ret = usb_bulk_read(udev, 129, (char *)out_msg, out_size, 5000); + if ( ret < 0 ) + return ret; + + if ( out_msg->header != 0x8800101B ) + return -1; + + if ( out_msg->type != (type | 0x20000000) ) + return -1; + + if ( (size_t)ret < sizeof(*out_msg) ) + return -1; + + if ( ntohs(out_msg->size) != ret - sizeof(*out_msg) + 4 ) + return -1; + + return ret - sizeof(*out_msg); + +} + int mkii_init(struct usb_device_info * dev) { - ERROR("Mk II protocol is not implemented yet"); - (void)dev; - return -1; + char buf[2048]; + struct mkii_message * msg; + enum device device; + int ret; + + printf("Initializing Mk II protocol...\n"); + + msg = (struct mkii_message *)buf; + + ret = mkii_send_receive(dev->udev, MKII_PING, msg, 0, msg, sizeof(buf)); + if ( ret != 0 ) + return -1; + + memcpy(msg->data, "/update/protocol_version", sizeof("/update/protocol_version")-1); + ret = mkii_send_receive(dev->udev, MKII_GET_PROTOCOL, msg, sizeof("/update/protocol_version")-1, msg, sizeof(buf)); + if ( ret != 2 || msg->data[0] != 0 || msg->data[1] != 0x32 ) + return -1; + + memcpy(msg->data, "/update/host_protocol_version\x00\x32", sizeof("/update/host_protocol_version\x00\x32")-1); + ret = mkii_send_receive(dev->udev, MKII_TELL_PROTOCOL, msg, sizeof("/update/host_protocol_version\x00\x32")-1, msg, sizeof(buf)); + if ( ret != 1 || msg->data[0] != 0 ) + return -1; + + device = mkii_get_device(dev); + + if ( ! dev->device ) + dev->device = device; + + if ( dev->device && device && dev->device != device ) { + ERROR("Device mishmash, expected %s, got %s", device_to_string(dev->device), device_to_string(device)); + return -1; + } + + dev->hwrev = mkii_get_hwrev(dev); + + return 0; } enum device mkii_get_device(struct usb_device_info * dev) { - ERROR("Not implemented yet"); - (void)dev; - return DEVICE_UNKNOWN; + char buf[2048]; + struct mkii_message * msg; + int ret; + + msg = (struct mkii_message *)buf; + + memcpy(msg->data, "/device/product_code", sizeof("/device/product_code")-1); + ret = mkii_send_receive(dev->udev, MKII_GET_DEVICE, msg, sizeof("/device/product_code")-1, msg, sizeof(buf)); + if ( ret < 2 || msg->data[0] != 0 || msg->data[1] == 0 ) + return DEVICE_UNKNOWN; + + msg->data[ret] = 0; + return device_from_string((char *)msg->data+1); } @@ -128,9 +228,19 @@ int mkii_set_rd_flags(struct usb_device_info * dev, const char * flags) { int16_t mkii_get_hwrev(struct usb_device_info * dev) { - ERROR("Not implemented yet"); - (void)dev; - return -1; + char buf[2048]; + struct mkii_message * msg; + int ret; + + msg = (struct mkii_message *)buf; + + memcpy(msg->data, "/device/hw_build", sizeof("/device/hw_build")-1); + ret = mkii_send_receive(dev->udev, MKII_GET_DEVICE, msg, sizeof("/device/hw_build")-1, msg, sizeof(buf)); + if ( ret < 2 || msg->data[0] != 0 || msg->data[1] == 0 ) + return -1; + + msg->data[ret] = 0; + return atoi(msg->data+1); } -- cgit v1.2.3