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/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(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -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. | ||||
|  | @ -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
	
	 George Norton
						George Norton