summaryrefslogtreecommitdiffstats
path: root/src/dfu.c
blob: e9de46f1176914dbacd1fb27c76480ee21b3807f (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
#include "project.h"

#ifdef INCLUDE_DFU_INTERFACE

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 = 3,
  .bAlternateSetting = 0,
  .bNumEndpoints = 0,
  .bInterfaceClass = 0xFE,
  .bInterfaceSubClass = 1,
  .bInterfaceProtocol = 1,
  .iInterface = 0,

  .extra = &dfu_function,
  .extralen = sizeof (dfu_function),
};


static void
dfu_detach_complete (usbd_device * usbd_dev, struct usb_setup_data *req)
{
  (void) req;
  (void) usbd_dev;

  gpio_set_mode (GPIOA, GPIO_MODE_INPUT, 0, GPIO15);
  gpio_set_mode (GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
                 GPIO_CNF_OUTPUT_PUSHPULL, GPIO10);
  gpio_set (GPIOA, GPIO10);
  scb_reset_core ();
}

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

  if ((req->bmRequestType != 0x21) || (req->bRequest != DFU_DETACH))
    return 0;                   /* Only accept class request. */

  *complete = dfu_detach_complete;

  return 1;
}
#endif