Basic support for rebooting into the bootloader. (#10)
This commit is contained in:
parent
992df01067
commit
69fdc8a4e2
|
@ -34,6 +34,7 @@
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
#include "pico/usb_device.h"
|
#include "pico/usb_device.h"
|
||||||
#include "pico/multicore.h"
|
#include "pico/multicore.h"
|
||||||
|
#include "pico/bootrom.h"
|
||||||
#include "AudioClassCommon.h"
|
#include "AudioClassCommon.h"
|
||||||
|
|
||||||
#include "run.h"
|
#include "run.h"
|
||||||
|
@ -59,6 +60,10 @@ static struct {
|
||||||
.freq = 48000,
|
.freq = 48000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum vendor_cmds {
|
||||||
|
REBOOT_BOOTLOADER = 0
|
||||||
|
};
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
|
@ -646,6 +651,20 @@ static bool do_set_current(struct usb_setup_packet *setup) {
|
||||||
return false;
|
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) {
|
static bool ac_setup_request_handler(__unused struct usb_interface *interface, struct usb_setup_packet *setup) {
|
||||||
setup = __builtin_assume_aligned(setup, 4);
|
setup = __builtin_assume_aligned(setup, 4);
|
||||||
if (USB_REQ_TYPE_TYPE_CLASS == (setup->bmRequestType & USB_REQ_TYPE_TYPE_MASK)) {
|
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);
|
count_of(boot_device_interfaces), _get_descriptor_string);
|
||||||
|
|
||||||
assert(device);
|
assert(device);
|
||||||
|
|
||||||
|
device->setup_request_handler = ad_setup_request_handler;
|
||||||
audio_set_volume(DEFAULT_VOLUME);
|
audio_set_volume(DEFAULT_VOLUME);
|
||||||
_audio_reconfigure();
|
_audio_reconfigure();
|
||||||
|
|
||||||
|
|
|
@ -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):
|
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.
|
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.
|
|
@ -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.")
|
Loading…
Reference in New Issue