Skip to content

Commit fe373a5

Browse files
switch: Fix compatibility with controllers which don't implement SPI reading properly
1 parent 42c9cd9 commit fe373a5

File tree

2 files changed

+53
-40
lines changed

2 files changed

+53
-40
lines changed

ios/ios_pad/source/controllers/switch_controller.c

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -444,18 +444,18 @@ static void handle_command_response(Controller* controller, SwitchCommandRespons
444444
{
445445
SwitchData* sdata = (SwitchData*) controller->additionalData;
446446

447-
DEBUG_PRINT("subcmd respone %d\n", resp->command);
447+
DEBUG_PRINT("subcmd respone 0x%x\n", resp->command);
448448

449449
if ((resp->ack & 0x80) == 0) {
450-
DEBUG_PRINT("switch subcmd %d failed\n", resp->command);
450+
DEBUG_PRINT("switch subcmd 0x%x failed\n", resp->command);
451451
// if we failed during one of the stages, just fall back to simple input
452452
controller->isReady = 1;
453453
return;
454454
}
455455

456456
if (resp->command == SWITCH_COMMAND_REQUEST_DEVICE_INFO) {
457457
sdata->device = resp->device_info.device_type;
458-
DEBUG_PRINT("device type %d\n", sdata->device);
458+
DEBUG_PRINT("device type 0x%x\n", sdata->device);
459459

460460
// Get the configuration again, now that we have the actual device type
461461
controller->type = switchDeviceToControllerType(sdata->device);
@@ -474,8 +474,8 @@ static void handle_command_response(Controller* controller, SwitchCommandRespons
474474
sdata->device == SWITCH_DEVICE_JOYCON_RIGHT || /*sdata->device == SWITCH_DEVICE_TP_JOYCON_RIGHT ||*/
475475
sdata->device == SWITCH_DEVICE_PRO || /*sdata->device == SWITCH_DEVICE_TP_PRO ||*/
476476
sdata->device == SWITCH_DEVICE_N64) && switchConfigCalibrationEnabled(controller)) {
477-
// Start by reading the left user calibration magic to check if user calibration exists
478-
readSpiFlash(controller, SWITCH_LEFT_USER_CALIBRATION_MAGIC_ADDRESS, 2);
477+
// Start by reading the user calibration
478+
readSpiFlash(controller, SWITCH_USER_CALIBRATION_ADDRESS, sizeof(SwitchRawUserStickCalibration));
479479
} else {
480480
// Don't need to wait for calibration, controller is ready now
481481
controller->isReady = 1;
@@ -484,42 +484,42 @@ static void handle_command_response(Controller* controller, SwitchCommandRespons
484484
uint32_t address = bswap32(resp->spi_flash_read.address);
485485

486486
switch (address) {
487-
case SWITCH_LEFT_USER_CALIBRATION_MAGIC_ADDRESS:
488-
// Check for user calibration
489-
if (resp->spi_flash_read.data[0] == 0xb2 && resp->spi_flash_read.data[1] == 0xa1) {
490-
// Read user calibration
491-
readSpiFlash(controller, SWITCH_LEFT_USER_CALIBRATION_ADDRESS, sizeof(SwitchRawStickCalibrationLeft));
492-
} else {
493-
// Fall back to factory calibration
494-
readSpiFlash(controller, SWITCH_LEFT_FACTORY_CALIBRATION_ADDRESS, sizeof(SwitchRawStickCalibrationLeft));
487+
case SWITCH_USER_CALIBRATION_ADDRESS: {
488+
SwitchRawUserStickCalibration* calibration = (SwitchRawUserStickCalibration*) resp->spi_flash_read.data;
489+
490+
if (calibration->left_magic == SWITCH_USER_CALIBRATION_MAGIC) {
491+
parseLeftRawStickCalibration(sdata, &calibration->left_calibration);
492+
sdata->has_left_calib = 1;
493+
}
494+
if (calibration->right_magic == SWITCH_USER_CALIBRATION_MAGIC) {
495+
parseRightRawStickCalibration(sdata, &calibration->right_calibration);
496+
sdata->has_right_calib = 1;
495497
}
496-
break;
497-
case SWITCH_LEFT_FACTORY_CALIBRATION_ADDRESS:
498-
case SWITCH_LEFT_USER_CALIBRATION_ADDRESS:
499-
// parse the calibration data
500-
parseLeftRawStickCalibration(sdata, (SwitchRawStickCalibrationLeft*) resp->spi_flash_read.data);
501498

502-
// continue with reading the right calibration magic
503-
readSpiFlash(controller, SWITCH_RIGHT_USER_CALIBRATION_MAGIC_ADDRESS, 2);
504-
break;
505-
case SWITCH_RIGHT_USER_CALIBRATION_MAGIC_ADDRESS:
506-
// Check for user calibration
507-
if (resp->spi_flash_read.data[0] == 0xb2 && resp->spi_flash_read.data[1] == 0xa1) {
508-
// Read user calibration
509-
readSpiFlash(controller, SWITCH_RIGHT_USER_CALIBRATION_ADDRESS, sizeof(SwitchRawStickCalibrationRight));
499+
// Check if we have both calibrations already or if we need to read factory calibrations
500+
if (sdata->has_left_calib && sdata->has_right_calib) {
501+
setInputReportMode(controller, SWITCH_INPUT_REPORT_ID);
510502
} else {
511-
// Fall back to factory calibration
512-
readSpiFlash(controller, SWITCH_RIGHT_FACTORY_CALIBRATION_ADDRESS, sizeof(SwitchRawStickCalibrationRight));
503+
readSpiFlash(controller, SWITCH_FACTORY_CALIBRATION_ADDRESS, sizeof(SwitchRawFactoryStickCalibration));
513504
}
514505
break;
515-
case SWITCH_RIGHT_FACTORY_CALIBRATION_ADDRESS:
516-
case SWITCH_RIGHT_USER_CALIBRATION_ADDRESS:
517-
// parse the calibration data
518-
parseRightRawStickCalibration(sdata, (SwitchRawStickCalibrationRight*) resp->spi_flash_read.data);
506+
}
507+
case SWITCH_FACTORY_CALIBRATION_ADDRESS: {
508+
SwitchRawFactoryStickCalibration* calibration = (SwitchRawFactoryStickCalibration*) resp->spi_flash_read.data;
509+
510+
if (!sdata->has_left_calib) {
511+
parseLeftRawStickCalibration(sdata, &calibration->left_calibration);
512+
sdata->has_left_calib = 1;
513+
}
514+
if (!sdata->has_right_calib) {
515+
parseRightRawStickCalibration(sdata, &calibration->right_calibration);
516+
sdata->has_right_calib = 1;
517+
}
519518

520519
// we can now enable full reports
521520
setInputReportMode(controller, SWITCH_INPUT_REPORT_ID);
522521
break;
522+
}
523523
default:
524524
DEBUG_PRINT("switch: unknown SPI read from %lx size %d\n", address, resp->spi_flash_read.size);
525525
break;

ios/ios_pad/source/controllers/switch_controller.h

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@ typedef struct {
4141
uint8_t led;
4242

4343
// Calibration for full reports
44+
uint8_t has_left_calib;
4445
SwitchStickCalibration left_calib_x;
45-
SwitchStickCalibration right_calib_x;
4646
SwitchStickCalibration left_calib_y;
47+
uint8_t has_right_calib;
48+
SwitchStickCalibration right_calib_x;
4749
SwitchStickCalibration right_calib_y;
4850

4951
// Extents for basic reports
@@ -83,14 +85,11 @@ enum {
8385
#define SWITCH_AXIS_Y(data) ((data[1] >> 4) | (data[2] << 4))
8486
typedef uint8_t SwitchAxis[3];
8587

86-
#define SWITCH_LEFT_FACTORY_CALIBRATION_ADDRESS 0x603d
87-
#define SWITCH_RIGHT_FACTORY_CALIBRATION_ADDRESS 0x6046
88+
// https://github.com/ndeadly/MissionControl/blob/c3157607eb1dedf78fc23835d7d0af4fe05a513a/mc_mitm/source/controllers/emulated_switch_controller.cpp#L274-L281
89+
#define SWITCH_FACTORY_CALIBRATION_ADDRESS 0x603d
90+
#define SWITCH_USER_CALIBRATION_ADDRESS 0x8010
8891

89-
#define SWITCH_LEFT_USER_CALIBRATION_MAGIC_ADDRESS 0x8010
90-
#define SWITCH_LEFT_USER_CALIBRATION_ADDRESS 0x8012
91-
92-
#define SWITCH_RIGHT_USER_CALIBRATION_MAGIC_ADDRESS 0x801b
93-
#define SWITCH_RIGHT_USER_CALIBRATION_ADDRESS 0x801d
92+
#define SWITCH_USER_CALIBRATION_MAGIC 0xb2a1
9493

9594
typedef struct PACKED {
9695
SwitchAxis max;
@@ -106,6 +105,20 @@ typedef struct PACKED {
106105
} SwitchRawStickCalibrationRight;
107106
CHECK_SIZE(SwitchRawStickCalibrationRight, 0x09);
108107

108+
typedef struct PACKED {
109+
uint16_t left_magic;
110+
SwitchRawStickCalibrationLeft left_calibration;
111+
uint16_t right_magic;
112+
SwitchRawStickCalibrationRight right_calibration;
113+
} SwitchRawUserStickCalibration;
114+
CHECK_SIZE(SwitchRawUserStickCalibration, 0x16);
115+
116+
typedef struct PACKED {
117+
SwitchRawStickCalibrationLeft left_calibration;
118+
SwitchRawStickCalibrationRight right_calibration;
119+
} SwitchRawFactoryStickCalibration;
120+
CHECK_SIZE(SwitchRawFactoryStickCalibration, 0x12);
121+
109122
typedef struct PACKED {
110123
uint8_t command;
111124
union {

0 commit comments

Comments
 (0)