From 77654ece88e9f58c774be5b9d921156eaeed00ce Mon Sep 17 00:00:00 2001
From: C-Glick <colton.glick@gmail.com>
Date: Sun, 30 Jan 2022 20:29:07 -0600
Subject: [PATCH] Started work on DFU flashing, need to figure out how to send
 setup requests from host

---
 .../src/hal/src/usb.c                         |  19 +-
 .../tools/make/flash_dfu/cfusb.py             | 201 ++++++++++++++++++
 .../tools/make/flash_dfu/testdfu.py           |   6 +
 3 files changed, 224 insertions(+), 2 deletions(-)
 create mode 100644 crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/cfusb.py
 create mode 100644 crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/testdfu.py

diff --git a/crazyflie_software/crazyflie-firmware-2021.06/src/hal/src/usb.c b/crazyflie_software/crazyflie-firmware-2021.06/src/hal/src/usb.c
index ec2ee5e95..f129b089f 100644
--- a/crazyflie_software/crazyflie-firmware-2021.06/src/hal/src/usb.c
+++ b/crazyflie_software/crazyflie-firmware-2021.06/src/hal/src/usb.c
@@ -48,6 +48,8 @@
 #include "crtp.h"
 #include "static_mem.h"
 
+#include "debug.h"
+
 
 NO_DMA_CCM_SAFE_ZERO_INIT __ALIGN_BEGIN USB_OTG_CORE_HANDLE    USB_OTG_dev __ALIGN_END ;
 
@@ -177,10 +179,23 @@ static uint8_t usbd_cf_Setup(void *pdev , USB_SETUP_REQ  *req)
                       USB_RX_TX_PACKET_SIZE);
       rxStopped = false;
     }
-  } else {
+  } else if(command == 0x02){
+    //transition to DFU bootloader mode
+
+    // arm-none-eabi-gcc 4.9.0 does not correctly inline this
+    //     //     // MSP function, so we write it out explicitly here.
+    __set_MSP(*((uint32_t*) 0x00000000));
+    //__ASM volatile ("movs r3, #0\nldr r3, [r3, #0]\nMSR msp, r3\n" : : : "r3", "sp");
+
+    ((void (*)(void)) *((uint32_t*) 0x00000004))();
+
+    while (1);
+  }
+  
+   else {
     crtpSetLink(radiolinkGetLink());
   }
-
+  DEBUG_PRINT("USB setup request: %d, %d, %d, %d, %d ",req->bmRequest, req->bRequest, req->wValue, req->wIndex, req->wLength);
   return USBD_OK;
 }
 
diff --git a/crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/cfusb.py b/crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/cfusb.py
new file mode 100644
index 000000000..349c212cc
--- /dev/null
+++ b/crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/cfusb.py
@@ -0,0 +1,201 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+#     ||          ____  _ __
+#  +------+      / __ )(_) /_______________ _____  ___
+#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
+#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
+#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
+#
+#  Copyright (C) 2011-2013 Bitcraze AB
+#
+#  Crazyflie Nano Quadcopter Client
+#
+#  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.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+#  MA  02110-1301, USA.
+"""
+USB driver for the Crazyflie.
+"""
+import logging
+import os
+
+import usb
+
+__author__ = 'Bitcraze AB'
+__all__ = ['CfUsb']
+
+logger = logging.getLogger(__name__)
+
+USB_VID = 0x0483
+USB_PID = 0x5740
+
+try:
+    import usb.core
+
+    pyusb_backend = None
+    if os.name == 'nt':
+        import usb.backend.libusb0 as libusb0
+
+        pyusb_backend = libusb0.get_backend()
+    pyusb1 = True
+
+except Exception:
+    pyusb1 = False
+
+
+def _find_devices():
+    """
+    Returns a list of CrazyRadio devices currently connected to the computer
+    """
+    ret = []
+
+    logger.info('Looking for devices....')
+
+    if pyusb1:
+        for d in usb.core.find(idVendor=USB_VID, idProduct=USB_PID, find_all=1,
+                               backend=pyusb_backend):
+            if d.manufacturer == 'Bitcraze AB':
+                ret.append(d)
+    else:
+        busses = usb.busses()
+        for bus in busses:
+            for device in bus.devices:
+                if device.idVendor == USB_VID:
+                    if device.idProduct == USB_PID:
+                        ret += [device, ]
+
+    return ret
+
+
+class CfUsb:
+    """ Used for communication with the Crazyradio USB dongle """
+
+    def __init__(self, device=None, devid=0):
+        """ Create object and scan for USB dongle if no device is supplied """
+        self.dev = None
+        self.handle = None
+        self._last_write = 0
+        self._last_read = 0
+
+        if device is None:
+            devices = _find_devices()
+            try:
+                self.dev = devices[devid]
+            except Exception:
+                self.dev = None
+
+        if self.dev:
+            if (pyusb1 is True):
+                self.dev.set_configuration(1)
+                self.handle = self.dev
+                self.version = float(
+                    '{0:x}.{1:x}'.format(self.dev.bcdDevice >> 8,
+                                         self.dev.bcdDevice & 0x0FF))
+            else:
+                self.handle = self.dev.open()
+                self.handle.setConfiguration(1)
+                self.handle.claimInterface(0)
+                self.version = float(self.dev.deviceVersion)
+
+    def get_serial(self):
+        # The signature for get_string has changed between versions to 1.0.0b1,
+        # 1.0.0b2 and 1.0.0. Try the old signature first, if that fails try
+        # the newer one.
+        try:
+            return usb.util.get_string(self.dev, 255, self.dev.iSerialNumber)
+        except (usb.core.USBError, ValueError):
+            return usb.util.get_string(self.dev, self.dev.iSerialNumber)
+
+    def close(self):
+        if (pyusb1 is False):
+            if self.handle:
+                self.handle.releaseInterface()
+        else:
+            if self.dev:
+                usb.util.dispose_resources(self.dev)
+
+        self.handle = None
+        self.dev = None
+
+    def scan(self):
+        # TODO: Currently only supports one device
+        if self.dev:
+            return [('usb://0', '')]
+        return []
+
+    def set_crtp_to_usb(self, crtp_to_usb):
+        if crtp_to_usb:
+            _send_vendor_setup(self.handle, 0x01, 0x01, 1, ())
+        else:
+            _send_vendor_setup(self.handle, 0x01, 0x01, 0, ())
+
+    def set_cf_to_dfu(self):
+        _send_vendor_setup(self.handle, 0x01, 0x01, 2, ())
+
+
+    # Data transfers
+    def send_packet(self, dataOut):
+        """ Send a packet and receive the ack from the radio dongle
+            The ack contains information about the packet transmission
+            and a data payload if the ack packet contained any """
+        try:
+            if (pyusb1 is False):
+                self.handle.bulkWrite(1, dataOut, 20)
+            else:
+                self.handle.write(endpoint=1, data=dataOut, timeout=20)
+        except usb.USBError:
+            pass
+
+    def receive_packet(self):
+        dataIn = ()
+        try:
+            if (pyusb1 is False):
+                dataIn = self.handle.bulkRead(0x81, 64, 20)
+            else:
+                dataIn = self.handle.read(0x81, 64, timeout=20)
+        except usb.USBError as e:
+            try:
+                if e.backend_error_code == -7 or e.backend_error_code == -116:
+                    # Normal, the read was empty
+                    pass
+                else:
+                    raise IOError('Crazyflie disconnected')
+            except AttributeError:
+                # pyusb < 1.0 doesn't implement getting the underlying error
+                # number and it seems as if it's not possible to detect
+                # if the cable is disconnected. So this detection is not
+                # supported, but the "normal" case will work.
+                pass
+
+        return dataIn
+
+
+# Private utility functions
+def _send_vendor_setup(handle, request, value, index, data):
+    if pyusb1:
+        handle.ctrl_transfer(usb.TYPE_VENDOR, request, wValue=value,
+                             wIndex=index, timeout=1000, data_or_wLength=data)
+    else:
+        handle.controlMsg(usb.TYPE_VENDOR, request, data, value=value,
+                          index=index, timeout=1000)
+
+
+def _get_vendor_setup(handle, request, value, index, length):
+    if pyusb1:
+        return handle.ctrl_transfer(usb.TYPE_VENDOR | 0x80, request,
+                                    wValue=value, wIndex=index, timeout=1000,
+                                    data_or_wLength=length)
+    else:
+        return handle.controlMsg(usb.TYPE_VENDOR | 0x80, request, length,
+                                 value=value, index=index, timeout=1000)
diff --git a/crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/testdfu.py b/crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/testdfu.py
new file mode 100644
index 000000000..e000311dd
--- /dev/null
+++ b/crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/testdfu.py
@@ -0,0 +1,6 @@
+from cfusb import CfUsb
+
+#TODO this devieid might need to be dynamic?
+cfusb = CfUsb(devid=int(0))
+
+cfusb.set_crtp_to_usb(True)
\ No newline at end of file
-- 
GitLab