1
0
mirror of git://projects.qi-hardware.com/ben-wpan.git synced 2024-11-23 17:46:16 +02:00
ben-wpan/atusb/fw/usb/dfu_common.c

102 lines
2.4 KiB
C
Raw Normal View History

/*
* boot/dfu_common.c - DFU protocol engine parts common to App/DFU
*
* Written 2008-2011, 2013-2014 by Werner Almesberger
* Copyright 2008-2011, 2013-2014 Werner Almesberger
*
* 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 2 of the License, or
* (at your option) any later version.
*/
/*
* http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf
*/
/*
* A few, erm, shortcuts:
*
* - we don't bother with the app* states since DFU is all this firmware does
* - after DFU_DNLOAD, we just block until things are written, so we never
* enter dfuDNLOAD_SYNC or dfuDNBUSY
* - no dfuMANIFEST_SYNC, dfuMANIFEST, or dfuMANIFEST_WAIT_RESET
* - to keep our buffers small, we only accept EP0-sized blocks
*/
#include <stdbool.h>
#include <stdint.h>
#include "usb.h"
#include "dfu.h"
#include "board.h"
#include "../sernum.h"
#ifndef NULL
#define NULL 0
#endif
#define debug(...)
#define error(...)
static const uint8_t functional_descriptor[] = {
9, /* bLength */
DFU_DT_FUNCTIONAL, /* bDescriptorType */
0xf, /* bmAttributes (claim omnipotence :-) */
LE(0xffff), /* wDetachTimeOut (we're very patient) */
LE(EP0_SIZE), /* wTransferSize */
LE(0x101), /* bcdDFUVersion */
};
/*
* The worst-case activity would be flashing a one page and erasing another
* one, would should take less than 10 ms. A 100 ms timeout ought to be plenty.
*/
struct dfu dfu = {
OK, /* bStatus */
LE(100), 0, /* bwPollTimeout, 100 ms */
dfuIDLE, /* bState */
0, /* iString */
};
bool dfu_setup_common(const struct setup_request *setup)
{
switch (setup->bmRequestType | setup->bRequest << 8) {
case DFU_FROM_DEV(DFU_GETSTATUS):
debug("DFU_GETSTATUS\n");
usb_send(&eps[0], (uint8_t *) &dfu, sizeof(dfu), NULL, NULL);
return 1;
case DFU_TO_DEV(DFU_CLRSTATUS):
debug("DFU_CLRSTATUS\n");
dfu.state = dfuIDLE;
dfu.status = OK;
return 1;
case DFU_FROM_DEV(DFU_GETSTATE):
debug("DFU_GETSTATE\n");
usb_send(&eps[0], &dfu.state, 1, NULL, NULL);
return 1;
default:
error("DFU rt %x, rq%x ?\n",
setup->bmRequestType, setup->bRequest);
return 0;
}
}
bool dfu_my_descr(uint8_t type, uint8_t index, const uint8_t **reply,
uint8_t *size)
{
if (type != DFU_DT_FUNCTIONAL)
return sernum_get_descr(type, index, reply, size);
*reply = functional_descriptor;
*size = sizeof(functional_descriptor);
return 1;
}