Basic support for rebooting into the bootloader.

This commit is contained in:
george-norton 2023-04-12 12:31:27 +01:00
parent 992df01067
commit e7f788a72c
3 changed files with 65 additions and 1 deletions

View File

@ -34,6 +34,7 @@
#include "pico/stdlib.h"
#include "pico/usb_device.h"
#include "pico/multicore.h"
#include "pico/bootrom.h"
#include "AudioClassCommon.h"
#include "run.h"
@ -59,6 +60,10 @@ static struct {
.freq = 48000,
};
enum vendor_cmds {
REBOOT_BOOTLOADER = 0
};
int main(void) {
setup();
@ -646,6 +651,20 @@ static bool do_set_current(struct usb_setup_packet *setup) {
return false;
}
static bool ad_setup_request_handler(__unused struct usb_device *device, struct usb_setup_packet *setup) {
setup = __builtin_assume_aligned(setup, 4);
if (USB_REQ_TYPE_TYPE_VENDOR == (setup->bmRequestType & USB_REQ_TYPE_TYPE_MASK)) {
// To prevent badly behaving software from accidentally triggering a reboot, e expect
// the wValue to be equal to the Ploopy vendor id.
if (setup->bRequest == REBOOT_BOOTLOADER && setup->wValue == 0x2E8A) {
reset_usb_boot(0, 0);
// reset_usb_boot does not return, so we will not respond to this command.
return true;
}
}
return false;
}
static bool ac_setup_request_handler(__unused struct usb_interface *interface, struct usb_setup_packet *setup) {
setup = __builtin_assume_aligned(setup, 4);
if (USB_REQ_TYPE_TYPE_CLASS == (setup->bmRequestType & USB_REQ_TYPE_TYPE_MASK)) {
@ -726,6 +745,8 @@ void usb_sound_card_init() {
count_of(boot_device_interfaces), _get_descriptor_string);
assert(device);
device->setup_request_handler = ad_setup_request_handler;
audio_set_volume(DEFAULT_VOLUME);
_audio_reconfigure();

View File

@ -17,7 +17,21 @@ Run `filter_test` to process the PCM samples. The `filter_test` program takes tw
You can listen to the PCM files using ffplay (which is usually included with ffmpeg):
```
./ffplay -f s16le -ar 48000 -ac 2 output.pcm
ffplay -f s16le -ar 48000 -ac 2 output.pcm
```
If there are no obvious problems, go ahead and flash your firmware.
## reboot_bootloader.py
If your Ploopy Headphones firmware is new enough, it has support for a USB vendor command that will cause the RP2040 to reboot into the
bootloader. This will enable you to update the firmware without having to remove the case and short the pins on the board.
### Usage
Connect the Ploopy headphones DAC and run:
```
./reboot_bootloader.py
```
You will need python3 and the pyusb module. If you get a permission denied error you may need to configure your udev rules, or run the
script with administrator privileges.

View File

@ -0,0 +1,29 @@
#!/usr/bin/python3
import usb.core
from usb.util import *
REBOOT_BOOTLOADER = 0
PLOOPY_VID = 0x2e8a
PLOOPY_PID = 0xfedd
device_count = 0
# Find all connected Ploopy headphone devices
for dev in usb.core.find(find_all=True, idVendor=PLOOPY_VID, idProduct=PLOOPY_PID):
device_count += 1
# The vendor command expects the wValue to be equal to the Ploopy vendor id. This
# will hopefully prevent badly behaved software from accidentally triggering bootloader
# mode.
try:
dev.ctrl_transfer(CTRL_RECIPIENT_DEVICE | CTRL_TYPE_VENDOR, REBOOT_BOOTLOADER, PLOOPY_VID)
except Exception as e:
# The headphones do not respond to the vendor command, as they have already rebooted,
# so for now, we always end up here.
if e.errno == 32:
# libusb pipe error, this is expected. OpenUSB doesnt report an error.
pass
else:
print(e)
print(f"Sent a reboot command to {device_count} Ploopy devices.")