Skip to content

Commit d245541

Browse files
committed
fl16: Add fwupd BOS descriptor
This allows fwupd to automatically detect that this device supports the rp_pico protocol. So we don't have to upstream a quirk to fwupd and wait for distributions to update their package. It will work with fwupd as old as 2.0.2 but is not present on the 1.9.X maintenance branch. The quirk is at keyboards/framework/fwupd.quirk and the binary data is generated with: `contrib/generate-ds20.py fwupd.quirk` It strips away the vid/pid because that is determined by USB enumeration. That means the same quirk can be used for all our keyboards. See: - https://fwupd.github.io/libfwupdplugin/ds20.html - https://github.com/fwupd/fwupd/tree/main/plugins/rp-pico Signed-off-by: Daniel Schaefer <dhs@frame.work>
1 parent 52d1987 commit d245541

File tree

5 files changed

+92
-6
lines changed

5 files changed

+92
-6
lines changed

keyboards/framework/config.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,6 @@
141141
//#define NO_ACTION_LAYER
142142
//#define NO_ACTION_TAPPING
143143
//#define NO_ACTION_ONESHOT
144+
145+
// Add BOS descriptor to tell fwupd that we support rpi-pico protocol
146+
#define FWUPD_CAP

keyboards/framework/fwupd.quirk

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[USB\VID_32AC&PID_0013]
2+
Plugin=rp_pico
3+
Flags=internal
4+
Icon=input-keyboard
5+
CounterpartGuid=BLOCK\VEN_2E8A&DEV_0003

tmk_core/protocol/chibios/usb_main.c

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,20 @@ static void keyboard_idle_timer_cb(struct ch_virtual_timer *, void *arg);
7575
report_keyboard_t keyboard_report_sent = {{0}};
7676
report_mouse_t mouse_report_sent = {0};
7777

78+
#if defined(FWUPD_CAP)
79+
static uint8_t fwupd_descriptor_set[] __attribute__((aligned(4))) = {
80+
// Generated with `~/clone/fwupd/contrib/generate-ds20.py fwup.quirk`
81+
0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x3d, 0x72, 0x70, 0x5f, 0x70, 0x69,
82+
0x63, 0x6f, 0x0a, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x3d, 0x69, 0x6e, 0x74,
83+
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x0a, 0x49, 0x63, 0x6f, 0x6e, 0x3d, 0x69,
84+
0x6e, 0x70, 0x75, 0x74, 0x2d, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72,
85+
0x64, 0x0a, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x61, 0x72,
86+
0x74, 0x47, 0x75, 0x69, 0x64, 0x3d, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5c,
87+
0x56, 0x45, 0x4e, 0x5f, 0x32, 0x45, 0x38, 0x41, 0x26, 0x44, 0x45, 0x56,
88+
0x5f, 0x30, 0x30, 0x30, 0x33
89+
};
90+
#endif
91+
7892
#if defined(MSOS2_CAP)
7993
static uint8_t msos_descriptor_set[] __attribute__((aligned(4))) = {
8094
//
@@ -785,6 +799,33 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
785799
return TRUE;
786800
}
787801

802+
#if defined(FWUPD_CAP)
803+
// if (usbp->setup[0] == 0xC0) {
804+
// dprintf("zoid. Vendor request\n");
805+
// dprintf("zoid:\n bmRequestType: %d\n bRequest: %d\n wValue: %d %d\n wIndex: %d %d\n wLength: %d %d\n",
806+
// usbp->setup[0], usbp->setup[1], usbp->setup[2], usbp->setup[3], usbp->setup[4], usbp->setup[5], usbp->setup[6], usbp->setup[7]);
807+
// }
808+
/* Handle Vendor Specific Request */
809+
if (
810+
//usbp->setup[0] == (USB_RTYPE_TYPE_VENDOR | USB_RTYPE_DIR_HOST2DEV | USB_RTYPE_RECIPIENT_DEVICE)
811+
usbp->setup[0] == 0xC0
812+
// Microsoft vendor code = 0x01
813+
// FWUPD vendor code = 0x2a
814+
// wRequest
815+
&& usbp->setup[1] == 0x2a
816+
// wValue
817+
&& usbp->setup[2] == 0x00 && usbp->setup[3] == 0x00
818+
// wIndex: MS_OS_20_DESCRIPTOR_INDEX
819+
&& usbp->setup[4] == 0x07 && usbp->setup[5] == 0x00
820+
// wLength: 0x0059
821+
&& usbp->setup[6] == 0x59 && usbp->setup[7] == 0x00
822+
) {
823+
//dprint("zoid: Detected MS OS 2.0 descriptor request\n");
824+
usbSetupTransfer(usbp, &fwupd_descriptor_set[0], 0x59, NULL);
825+
return TRUE;
826+
}
827+
#endif
828+
788829
#if defined(MSOS2_CAP)
789830
/* Handle Vendor Specific Request */
790831
//if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_VENDOR) && ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_DEVICE)) {
@@ -797,17 +838,19 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
797838
if (
798839
//usbp->setup[0] == (USB_RTYPE_TYPE_VENDOR | USB_RTYPE_DIR_HOST2DEV | USB_RTYPE_RECIPIENT_DEVICE)
799840
usbp->setup[0] == 0xC0
800-
// Microsoft vendor code
801-
&& usbp->setup[1] == 0x01
841+
// Microsoft vendor code = 0x01
842+
// Framework vendor code = 0x2a
843+
&& usbp->setup[1] == 0x2a
802844
// wValue
803845
&& usbp->setup[2] == 0x00 && usbp->setup[3] == 0x00
804846
// wIndex: MS_OS_20_DESCRIPTOR_INDEX
805847
&& usbp->setup[4] == 0x07 && usbp->setup[5] == 0x00
806848
// wLength: 0x0048
807-
&& usbp->setup[6] == 0x48 && usbp->setup[7] == 0x00
849+
&& usbp->setup[6] == sizeof(fwupd_descriptor_set) && usbp->setup[7] == 0x00
808850
) {
809851
//dprint("zoid: Detected MS OS 2.0 descriptor request\n");
810-
usbSetupTransfer(usbp, &msos_descriptor_set[0], 0x48, NULL);
852+
// usbSetupTransfer(usbp, &msos_descriptor_set[0], 0x48, NULL);
853+
usbSetupTransfer(usbp, &fwupd_descriptor_set[0], sizeof(fwupd_descriptor_set), NULL);
811854
return TRUE;
812855
}
813856
//dprint("zoid: After\n");

tmk_core/protocol/usb_descriptor.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ const USB_Descriptor_Bos_t PROGMEM BosDescriptor = {
493493
},
494494
// 3 Bytes (=> 5 Bytes)
495495
// Value must be header + each cap
496-
#if defined(MSOS2_CAP)
496+
#if defined(MSOS2_CAP) || defined(FWUPD_CAP)
497497
.TotalLength = 0x0028,
498498
.NumDeviceCaps = 0x02,
499499
#else
@@ -508,10 +508,40 @@ const USB_Descriptor_Bos_t PROGMEM BosDescriptor = {
508508
.Type = 16,
509509
},
510510
// 5 Bytes (=> 12 Bytes / 0x0C Bytes)
511-
.DevCapabilityType = 2,
511+
.DevCapabilityType = 2, // USB 2.0 Extension Descriptor
512512
.Bytes = {0x00, 0x00, 0x00, 0x00},
513513
},
514514

515+
#ifdef FWUPD_CAP
516+
// See https://fwupd.github.io/libfwupdplugin/ds20.html
517+
.FwupdCap = {
518+
// 2 Bytes (=> 7 Bytes)
519+
.Header = {
520+
.Size = sizeof(USB_Descriptor_Capability_Msos_t),
521+
.Type = 16,
522+
},
523+
// 5 Bytes (=> 12 Bytes / 0x0C Bytes)
524+
.DevCapabilityType = 5, // Platform
525+
.Reserved = 0,
526+
// FWUPD {010aec63-f574-52cd-9dda-2852550d94f0}
527+
.PlatformCapabilityId = {
528+
0x63, 0xec, 0x0a, 0x01,
529+
0x74, 0xf5, 0xcd, 0x52,
530+
0x9d, 0xda, 0x28, 0x52,
531+
0x55, 0x0d, 0x94, 0xf0
532+
},
533+
.Set = {{
534+
// rp-pico protocol supported since fwupd 2.0.2
535+
// 0x00020002
536+
.WindowsVersion = {0x02, 0x00, 0x02, 0x00},
537+
// Length of the data returned by control request
538+
.TotalLength = 0x0059,
539+
.VendorCode = 0x2a,
540+
.AltEnumCode = 0,
541+
}},
542+
},
543+
#endif // FWUPD_CAP
544+
515545
#ifdef MSOS2_CAP
516546
// 28 Bytes (0x1C)
517547
.MsosCap = {

tmk_core/protocol/usb_descriptor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,12 @@ typedef struct
392392
uint8_t NumDeviceCaps; /**< The number of separate device capability descriptors in the BOS.
393393
*/
394394
USB_Descriptor_Capability_Usb20Ext_t Usb20ExtensionDevCap;
395+
#ifdef FWUPD_CAP
396+
USB_Descriptor_Capability_Msos_t FwupdCap;
397+
#endif
398+
#ifdef MSOS2_CAP
395399
USB_Descriptor_Capability_Msos_t MsosCap;
400+
#endif
396401
} ATTR_PACKED USB_Descriptor_Bos_t;
397402

398403
/** \brief Standard USB BOS Descriptor (USB-IF naming conventions).

0 commit comments

Comments
 (0)