Adding DFU to a USB HID device

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a working USB HID generic device using the ASF 3.34.1. I want to add DFU capability. I already have a DFU bootloader, what I need to do is add the DFU endpoint to the main HID device so that it can automatically reboot into DFU mode.

 

Is this supported, and if so how does it work? I can't seem to add a second USB service via the ASF wizard and there is no option for combined HID and DFU. If I select "composite" then HID is listed, but DFU is not.

 

I could go poking around in the ASF code to add DFU support, but Atmel claims to support it already so... how?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think the short answer to this is that it's not supported and not easy to implement.

 

DFU communicates over the control channel, it doesn't use endpoints. The ASF makes it difficult to add new code to handle these control requests. Also, with HID if you add in the DFU interface descriptors it breaks Windows HID driver because it doesn't know what to do with them. As such the best option is probably to create a deal composite device with the DFU separated off and an extra WCID descriptor thrown in to help Windows out.

 

Of course, Atmel don't actually support DFU in composite devices, or WCID... I have hacked WCID in before and it's probably possible to do with DFU as well, but it won't be easy. So for now I'm going to use a different method to enter the bootloader.

 

In the longer term I think rather than arsing about with the ASF stack, it would be easier to add HID support to the XMEGA fork of Kevin Mehall's stack I made. I already have working DFU and WCID code for that codebase and it's much more flexible, compact, easier to work with and faster than the ASF code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AIUI: I think what they do for AtmelICE/EDBG to update firmware is to tell it to reboot into DFU mode: so it is either in "normal" mode, or in DFU mode - in doesn't have DFU capability in "normal" mode ... ?

 

 

(and, I think,  that's why you sometimes get an apparently "dead" AtmelICE/EDBG after attempting a FW update - because it gets "stuck" in DFU mode ... ?)

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The way DFU is designed to work is that there are two modes: runtime and DFU.

 

Runtime is just the normal device firmware, acting as whatever kind of USB device it is, but with an extra DFU interface added. All that interface can do is go into DFU mode, which usually entails rebooting into the bootloader.

 

The idea is that if your device is working normally then the DFU tool on the host can tell it to go into the bootloader. You don't need a button or a jumper to do it manually.

 

It's the runtime bit that I am trying to implement. The requirements are adding two new sub descriptors to the device descriptor (an interface and a special DFU descriptor), and then handling control packets directed to that interface.

 

Unfortunately, adding that DFU interface to a HID device seems to upset Windows' HID driver and you get a code 10 error.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have the reverse problem. My device has no use for an HID/CDC or any other form of USB interface in run mode. It is normally pwered from a USB charger or power pack, but if powered from a PC USB port it will become a DFU device. I have failed dismally to write anything useful on the PC side, firstly because I'm not a Windows programmer, but also because all the examples I could find are expecting a dual-mode device.

I actually hate USB.

Quebracho seems to be the hardest wood.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

USB is pretty stupid, and worthy of ill feelings.

However, all you need to do is grab dfu-tool on the host side. What MCU are you using?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not an AVR. It's a Freescale part.

Yes, I have a utility that will work for bootloading from the PC, but my evil overlords and masters really wanted me to write my own to embed it in a GUI. I ended up calling a batch file from Java. Seems to work, but not ideal.

Quebracho seems to be the hardest wood.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dfu_util is open source.... I am going to try to build it on Windows at some point, to add support for .hex files.

 

Having said that, the DFU protocol is really simple. It might actually be easier to start from scratch with libusb.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I couldn't get libusb to work in my Eclipse/MinGW environment. Maybe I had the wrong .h files.

More likely I just don't know what I'm doing with Windows stuff, and when I get frustrated, there doesn't seem to be anywhere to ask, apart from Stack Overflow, where I've been belittled, berated and castigated, so I don't bother.

I used to write fantastic ASM for PCs back in the old days...

 

 

Quebracho seems to be the hardest wood.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Stack Overflow is a pretty wretched place. Even when you get an non-abusive answer, it's usually wrong.

 

Also, damn it Atmel.