feat: support test command

This commit is contained in:
awalol
2026-04-28 13:15:20 +08:00
parent 3a4b8494ea
commit 6c992af459
4 changed files with 63 additions and 15 deletions
+22 -3
View File
@@ -333,11 +333,16 @@ static void l2cap_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t
bt_disconnect(); bt_disconnect();
} }
} else if (channel == hid_control_cid) { } else if (channel == hid_control_cid) {
if (size > 1 && packet[0] == 0xA3) { if (packet[0] == 0xA3) {
uint8_t report_id = packet[1]; uint8_t report_id = packet[1];
feature_data[report_id].assign(packet + 1, packet + size); feature_data[report_id].assign(packet + 1, packet + size);
printf("[L2CAP] Stored Feature Report 0x%02X, len=%u\n", report_id, size - 1); printf("[L2CAP] Stored Feature Report 0x%02X, len=%u\n", report_id, size - 1);
} }
if (packet[0] == 0x00) {
printf("[L2CAP] Getting Test Result\n");
feature_data.erase(0x81);
get_feature_data(0x81,64);
}
printf("[L2CAP] HID Control data len=%u\n", size); printf("[L2CAP] HID Control data len=%u\n", size);
printf_hexdump(packet, size); printf_hexdump(packet, size);
bt_data_callback(CONTROL, packet, size); bt_data_callback(CONTROL, packet, size);
@@ -477,19 +482,33 @@ void bt_write(uint8_t *data, uint16_t len) {
} }
std::vector<uint8_t> get_feature_data(uint8_t reportId, uint16_t len) { std::vector<uint8_t> get_feature_data(uint8_t reportId, uint16_t len) {
if (feature_data.find(reportId) == feature_data.end() || feature_data[reportId].empty()) { if (!feature_data.contains(reportId) || feature_data[reportId].empty()) {
if (hid_control_cid != 0) { if (hid_control_cid != 0) {
uint8_t get_feature[] = {0x43, reportId}; uint8_t get_feature[] = {0x43, reportId};
l2cap_send(hid_control_cid, get_feature, len); l2cap_send(hid_control_cid, get_feature, len);
printf("[L2CAP] Requesting Feature Report 0x%02X\n", reportId); printf("[L2CAP] Requesting Get Feature Report 0x%02X\n", reportId);
} }
return {}; return {};
} }
return feature_data[reportId]; return feature_data[reportId];
} }
void set_feature_data(uint8_t reportId, uint8_t* data,uint16_t len) {
if (hid_control_cid != 0) {
uint8_t get_feature[len + 2];
get_feature[0] = 0x53;
get_feature[1] = reportId;
memcpy(get_feature + 2,data,len);
fill_feature_report_checksum(get_feature + 1,len + 1);
l2cap_send(hid_control_cid, get_feature, len + 2);
printf("[L2CAP] Requesting Set Feature Report 0x%02X\n", reportId);
printf_hexdump(get_feature,len + 2);
}
}
void init_feature() { void init_feature() {
get_feature_data(0x09, 20); get_feature_data(0x09, 20);
get_feature_data(0x20, 64); get_feature_data(0x20, 64);
get_feature_data(0x22, 64);
get_feature_data(0x05, 41); get_feature_data(0x05, 41);
} }
+1
View File
@@ -22,5 +22,6 @@ void bt_send_control(uint8_t *data, uint16_t len);
void bt_write(uint8_t* data,uint16_t len); void bt_write(uint8_t* data,uint16_t len);
std::vector<uint8_t> get_feature_data(uint8_t reportId,uint16_t len); std::vector<uint8_t> get_feature_data(uint8_t reportId,uint16_t len);
void init_feature(); void init_feature();
void set_feature_data(uint8_t reportId, uint8_t* data,uint16_t len);
#endif //DS5_BRIDGE_BT_H #endif //DS5_BRIDGE_BT_H
+7
View File
@@ -72,6 +72,8 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t rep
(void) buffer; (void) buffer;
(void) bufsize; (void) bufsize;
// INTERRUPT OUT
if (report_id == 0) {
switch (buffer[0]) { switch (buffer[0]) {
case 0x02: { case 0x02: {
uint8_t outputData[78]; uint8_t outputData[78];
@@ -87,6 +89,11 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t rep
} }
} }
} }
if (report_id == 0x80) {
set_feature_data(report_id,const_cast<uint8_t *>(buffer),bufsize);
return;
}
}
int main() { int main() {
vreg_set_voltage(VREG_VOLTAGE_1_20); vreg_set_voltage(VREG_VOLTAGE_1_20);
+22 -1
View File
@@ -110,6 +110,27 @@ inline void fill_output_report_checksum(uint8_t* outputData,size_t len)
outputData[len - 1] = (crc >> 24) & 0xFF; outputData[len - 1] = (crc >> 24) & 0xFF;
} }
inline uint32_t crc32_feature(const uint8_t *data, std::size_t size) {
// https://github.com/rafaelvaloto/Dualsense-Multiplatform/blob/main/Source/Private/GCore/Utils/CR32.cpp
uint32_t crc = ~0x2060efc3; // 0x53 seed
while (size--) {
crc ^= *data++;
for (unsigned i = 0; i < 8; i++)
crc = ((crc >> 1) ^ (0xEDB88320 & -(crc & 1)));
}
return ~crc;
}
inline void fill_feature_report_checksum(uint8_t *data, const size_t len) {
uint32_t crc = crc32_feature(data,len - 4);
data[len - 4] = (crc >> 0) & 0xFF;
data[len - 3] = (crc >> 8) & 0xFF;
data[len - 2] = (crc >> 16) & 0xFF;
data[len - 1] = (crc >> 24) & 0xFF;
}
enum PowerState : uint8_t { enum PowerState : uint8_t {
Discharging = 0x00, // Use PowerPercent Discharging = 0x00, // Use PowerPercent
Charging = 0x01, // Use PowerPercent Charging = 0x01, // Use PowerPercent
@@ -216,7 +237,7 @@ struct __attribute__((packed)) USBGetStateData { // 63
/*55 */ uint8_t AesCmac[8]; /*55 */ uint8_t AesCmac[8];
}; };
inline void print_hex(const int16_t* data,size_t size) { inline void print_hex(const uint8_t* data,size_t size) {
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(data[i]) << " "; std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(data[i]) << " ";
} }