Skip to content

8BitDo M30 New Firmwares #9679

@nathanielhourt

Description

@nathanielhourt

Is your feature request related to a problem? Please describe.
I want to update my M30 to the newest firmware release, which is v2.10, but this firmware seems to have a slightly different data format that fwupd doesn't understand yet.

The new format is trivially different from the old one, and is probably easy to implement, but I don't know the libfwupdplugin API at all and would like guidance.

Describe the solution you'd like
Either guidance so I can implement the requisite changes myself, or for someone more familiar with the codebase to implement the changes so we can update our firmwares again!

Describe alternatives you've considered
Well, I guess the main alternative would be to just not update... But my controller is malfunctioning and 8BitDo's advice is to update the firmware, so here we are.

Additional context
The M30 device type code on 8BitDo's API is 23, so we can list the available firmwares with curl:
curl -X POST -H "Type: 23" http://dl.8bitdo.com:8080/firmware/select
Pretty output:

{
   "error" : "",
   "list" : [
      {
         "androidDownload" : 0,
         "beta" : "",
         "date" : "2025-06-23",
         "exists" : false,
         "fileName" : "M30",
         "filePathName" : "/firmwareFile/upload/ca5c6c68-8247-42c4-a109-116b3a7c4918.dat",
         "fileSize" : 151608,
         "fileURL" : "/var/lib/tomcat9/webapps/firmwareFile/upload/ca5c6c68-8247-42c4-a109-116b3a7c4918.dat",
         "iOSDownload" : 0,
         "id" : 2018,
         "macDownload" : 923,
         "md5" : "424780ACCB0317D8CB9AAA6128C50DE2",
         "readme" : "1. 新增支持 Switch 2 主机。\r\n2. 修复 Switch 模式同时交换按键和切换方向键不能保存的问题。",
         "readme_en" : "1. Added support for Switch 2.\r\n2. Fixed the issue of the Controller where the settings cannot be saved when doing the button swapping and D-pad remapping in Switch mode.",
         "type" : 23,
         "version" : 2.00999999046326,
         "winDownload" : 7432
      },
      {
         "androidDownload" : 0,
         "beta" : "",
         "date" : "2023-06-27",
         "exists" : false,
         "fileName" : "M30",
         "filePathName" : "/firmwareFile/upload/090523b7-4ddf-4c3a-ab61-5388e398800a.dat",
         "fileSize" : 149560,
         "fileURL" : "/var/lib/tomcat9/webapps/firmwareFile/upload/090523b7-4ddf-4c3a-ab61-5388e398800a.dat",
         "iOSDownload" : 0,
         "id" : 1707,
         "macDownload" : 1890,
         "md5" : "D391953371F52DF0A333188FAE8A265D",
         "readme" : "1. 优化蓝牙连接的稳定性。",
         "readme_en" : "1. Optimized the stability over Bluetooth connection.",
         "type" : 23,
         "version" : 2,
         "winDownload" : 14901
      }
   ],
   "msgState" : 1
}

It doesn't say it in the output, but the top entry is v2.10 and the bottom entry is v2.00 (confirm by comparing "readme_en" field with M30's update log on https://support.8bitdo.com/) so we can download the latest at http://dl.8bitdo.com:8080/firmwareFile/upload/ca5c6c68-8247-42c4-a109-116b3a7c4918.dat and we get a file of 151608 bytes.

If we try to use this file with fwupdtool install-blob, we wind up with an error: file size incorrect, expected 0x13a00 got 0x2501c
After some trenching through fwupd/plugins/ebitdo/fu-ebitdo-firmware.c, I determined that the plugin reads the .dat file and parses a header of 0x1C bytes, but it only seems to care about the first 12 bytes, which contains a 4 byte version number, a 4 byte "destination address", and a 4 byte payload size. OK, great, so we can easily read the .dat and manually parse that header:

Version: 0xC9
Dest Addr: 0x08003400
Payload Sz: 0x13A00

The error is generated by subtracting the header size from the .dat file length, and comparing this difference with the payload size. It doesn't match, and the tool fails.

But what has changed is actually quite trivial: if we look in our .dat file at address 0x13A1C, where the ebitdo plugin expects to see EOF, we instead find what looks suspciously like another header! Let's parse it:

Version: 0xC9
Dest Addr: 0x01018000
Payload Sz: 0x11600

OK, so a second header is at 0x13A1C, describing a second payload at 0x13A38 for 0x11600 bytes. If we add the payload address and length, 0x13A38 + 0x11600, we get 0x25038 which is the total size of our file. So it appears to me that we have two payloads destined for different addresses.

I would expect that implementing support for this format change would be quite straightforward, but I've never worked in this codebase before and I suspect I might brick my controller if I just start trying things, so I'd like a bit of guidance before I try to implement the changes myself.

I have considered just splitting the dat file into two different dat files and trying to flash both of them separately, but I would also like confirmation that this would probably do the right thing before I try it. I'd rather not break my controller! =)

Is anyone more familiar with this protocol/library around to help me work this out? TIA!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions