aboutsummaryrefslogtreecommitdiffstats
path: root/app/dfu.c
blob: 29a2428e16e71cd5c41e0f5bcccc3173a679cc0b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include "project.h"

const struct usb_dfu_descriptor dfu_function = {
  .bLength = sizeof (struct usb_dfu_descriptor),
  .bDescriptorType = DFU_FUNCTIONAL,
  .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH,
  .wDetachTimeout = 255,
  .wTransferSize = 1024,
  .bcdDFUVersion = 0x011A,
};

const struct usb_interface_descriptor dfu_iface = {
  .bLength = USB_DT_INTERFACE_SIZE,
  .bDescriptorType = USB_DT_INTERFACE,
  .bInterfaceNumber = 1,
  .bAlternateSetting = 0,
  .bNumEndpoints = 0,
  .bInterfaceClass = 0xFE,
  .bInterfaceSubClass = 1,
  .bInterfaceProtocol = 1,
  .iInterface = 4,
  .extra = &dfu_function,
  .extralen = sizeof (dfu_function),
};


const struct usb_iface_assoc_descriptor dfu_iface_assoc = {
  .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
  .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
  .bFirstInterface = 1,
  .bInterfaceCount = 1,
  .bFunctionClass = 0xfe,
  .bFunctionSubClass = 1,
  .bFunctionProtocol = 1,
  .iFunction = 5,
};


static void
dfu_detach_complete (usbd_device *usbd_dev, struct usb_setup_data *req)
{
  (void) req;
  (void) usbd_dev;
  dfu_flag = 0xfee1dead;

  scb_reset_core();
}

enum usbd_request_return_codes
dfu_control_request (usbd_device *usbd_dev, struct usb_setup_data *req,
                     uint8_t **buf, uint16_t *len,
                     usbd_control_complete_callback *complete) {
  (void) buf;
  (void) len;
  (void) usbd_dev;

  if ((req->bmRequestType & 0x7F) != 0x21)
    return USBD_REQ_NEXT_CALLBACK;

  switch (req->bRequest)
  {
  case DFU_GETSTATUS: {
    (*buf) [0] = DFU_STATUS_OK;
    (*buf) [1] = 0;
    (*buf) [2] = 0;
    (*buf) [3] = 0;
    (*buf) [4] = STATE_APP_IDLE;
    (*buf) [5] = 0;         /* iString not used here */
    *len = 6;
    return USBD_REQ_HANDLED;
  }

  case DFU_GETSTATE:
    /* Return state with no state transision. */
    *buf[0] = STATE_APP_IDLE;
    *len = 1;
    return USBD_REQ_HANDLED;

  case DFU_DETACH:
    *complete = dfu_detach_complete;
    return USBD_REQ_HANDLED;
  }

  return USBD_REQ_NEXT_CALLBACK;
}