From 09782495ab8634caea5ad414c83190646f5bbd61 Mon Sep 17 00:00:00 2001 From: Allen Hill Date: Mon, 15 Jun 2026 12:03:01 -0700 Subject: [PATCH] Improve/correct several response bodies --- src/avclandrv.c | 117 +++++++++++++++++++++++++++++++++++++++++++++--- src/avclandrv.h | 29 +++++++----- src/sniffer.c | 6 +-- 3 files changed, 132 insertions(+), 20 deletions(-) diff --git a/src/avclandrv.c b/src/avclandrv.c index 471da7c..0e4d295 100644 --- a/src/avclandrv.c +++ b/src/avclandrv.c @@ -299,7 +299,7 @@ void AVCLAN_init() { cd_status.cds = cd_CD1; cd_status.disc = 1; - cd_status.state = cd_SEEKING_TRACK; + cd_status.state = cd_SEEKING | cd_SEEKING_TRACK; cd_status.flags = 0; cd_status.flags2 = 0xC0; @@ -947,10 +947,14 @@ response_t AVCLAN_handleframe(const AVCLAN_frame_t *in, AVCLAN_frame_t *out) { case PACK3(dev_COMM_v1, dev_COMM_CTRL, Current_Function): case PACK3(dev_COMM_v2, dev_COMM_CTRL, Current_Function): if ((b3 == dev_CD_CHANGER) && !AVCLAN_isPlaying()) { + if (cd_status.mins > 99) + cd_status.mins = 0; + if (cd_status.secs > 99) + cd_status.secs = 0; cd_status.state = cd_SEEKING | cd_SEEKING_TRACK; - cd_status.flags2 = 0x80; - AVCLAN_startPlaying(); + cd_status.flags2 = 0xc0; AVCLAN_generateStatus(out); + AVCLAN_startPlaying(); respond = r_NormalizeState; } break; @@ -984,10 +988,9 @@ response_t AVCLAN_handleframe(const AVCLAN_frame_t *in, AVCLAN_frame_t *out) { out->length = sizeof(function_change_resp); memcpy(out->data, function_change_resp, sizeof(function_change_resp)); out->data[3] = Enable_Function_Resp; - cd_status.state = cd_SEEKING | cd_SEEKING_TRACK; - cd_status.flags2 = 0xc0; - AVCLAN_startPlaying(); - respond = r_StartPlaying; + cd_status.state = 0; + cd_status.flags2 = 0x80; + respond = r_StatusReport; break; case PACK3(dev_COMM_v1, dev_CD_CHANGER, Disable_Function_Req): [[fallthrough]]; @@ -1002,6 +1005,24 @@ response_t AVCLAN_handleframe(const AVCLAN_frame_t *in, AVCLAN_frame_t *out) { out->peripheral_addr = HU_ADDR; respond = r_StatusReport; break; + case PACK3(dev_CMD_SW, dev_CD_CHANGER, Eject): + // "Eject" label is multiply wrong; proper meaning unclear: + // - First observed on initial multiple presses of "CD" button, + // triggering (after {0x00, dev_CD_CHANGER, dev_COMM_v1, Insertion, + // 0x01} response) proper activation of mockingboard/cd-changer. + // - Subsequently observed when pressing (technically + // releasing?) the fast-forward button (and not rewind? needs + // confirmation) + out->is_unicast = true; + out->peripheral_addr = HU_ADDR; + { + const uint8_t msg[] = {0x00, dev_CD_CHANGER, dev_COMM_v1, Insertion, + 0x01}; + out->length = sizeof(msg); + memcpy(out->data, msg, sizeof(msg)); + } + respond = r_Handled; + break; case PACK3(dev_CMD_SW, dev_CD_CHANGER, Initial_Report_Request): [[fallthrough]]; case PACK3(dev_STATUS, dev_CD_CHANGER, Initial_Report_Request): @@ -1064,6 +1085,71 @@ response_t AVCLAN_handleframe(const AVCLAN_frame_t *in, AVCLAN_frame_t *out) { AVCLAN_generateStatus(out); respond = r_TrackChange; break; + // case PACK3(dev_CMD_SW, dev_CD_CHANGER, CD_Enable_Random): + // cd_status.flags |= cd_RANDOM; + // out->is_unicast = true; + // out->peripheral_addr = HU_ADDR; + // { + // const uint8_t msg[] = {0x00, dev_CD_CHANGER, dev_COMM_v1, + // CD_Enable_Random, 0x01}; + // out->length = sizeof(msg); + // memcpy(out->data, msg, sizeof(msg)); + // } + // respond = r_StatusReport; + // break; + // case PACK3(dev_CMD_SW, dev_CD_CHANGER, CD_Disable_Random): + // cd_status.flags &= ~cd_RANDOM; + // AVCLAN_generateStatus(out); + // respond = r_Handled; + // break; + case PACK3(dev_CMD_SW, dev_CD_CHANGER, CD_Enable_Repeat): + cd_status.flags |= cd_REPEAT; + // out->is_unicast = true; + out->is_unicast = false; + out->peripheral_addr = 0x1FF; + { + // const uint8_t msg[] = {0x00, dev_CD_CHANGER, dev_CMD_SW, + // CD_Enable_Repeat, 0x01}; + // const uint8_t msg[] = {0x00, dev_CD_CHANGER, dev_CMD_SW, + // CD_Enable_Repeat, 0x00}; + // const uint8_t msg[] = {0x00, dev_CD_CHANGER, dev_CMD_SW, + // CD_Enable_Repeat}; + // const uint8_t msg[] = {0x00, dev_CD_CHANGER, dev_COMM_v1, + // CD_Enable_Repeat, 0x01}; + // const uint8_t msg[] = {0x00, dev_CD_CHANGER, dev_COMM_v1, + // CD_Enable_Repeat, 0x00}; + const uint8_t msg[] = {0x00, dev_CD_CHANGER, dev_COMM_v1, + CD_Enable_Repeat}; + out->length = sizeof(msg); + memcpy(out->data, msg, sizeof(msg)); + } + respond = r_StatusReport; + break; + // case PACK3(dev_CMD_SW, dev_CD_CHANGER, CD_Disable_Repeat): + // cd_status.flags &= ~cd_REPEAT; + // AVCLAN_generateStatus(out); + // respond = r_Handled; + // break; + // case PACK3(dev_CMD_SW, dev_CD_CHANGER, CD_Enable_Disk_Random): + // cd_status.flags |= cd_DISK_RANDOM; + // AVCLAN_generateStatus(out); + // respond = r_Handled; + // break; + // case PACK3(dev_CMD_SW, dev_CD_CHANGER, CD_Disable_Disk_Random): + // cd_status.flags &= ~cd_DISK_RANDOM; + // AVCLAN_generateStatus(out); + // respond = r_Handled; + // break; + // case PACK3(dev_CMD_SW, dev_CD_CHANGER, CD_Enable_Disk_Repeat): + // cd_status.flags |= cd_DISK_REPEAT; + // AVCLAN_generateStatus(out); + // respond = r_Handled; + // break; + // case PACK3(dev_CMD_SW, dev_CD_CHANGER, CD_Disable_Disk_Repeat): + // cd_status.flags &= ~cd_DISK_REPEAT; + // AVCLAN_generateStatus(out); + // respond = r_Handled; + // break; } } @@ -1075,6 +1161,23 @@ response_t AVCLAN_handleframe(const AVCLAN_frame_t *in, AVCLAN_frame_t *out) { RFrame_t *AVCLAN_statemachine(RFrame_t *resp) { AVCLAN_frame_t *out = resp->frame; switch (resp->r) { + case r_Ejection: { + const uint8_t play[] = {0x00, dev_COMM_CTRL, dev_COMM_v1, + Insertion, dev_CD_CHANGER, 0x01}; + out->length = sizeof(play); + memcpy(out->data, play, sizeof(play)); + } + resp->r = r_Report_Load; + break; + case r_Report_Load: + out->is_unicast = false; + out->peripheral_addr = 0x1FF; + out->length = sizeof(cdloading_resp) + 1; + memcpy(out->data, cdloading_resp, sizeof(cdloading_resp)); + out->data[1] = dev_STATUS; + out->data[2] = Loading_Status_Report; + resp->r = r_Handled; + break; case r_TrackChange: AVCLAN_setTime(0x00, 0x00); [[fallthrough]]; case r_NormalizeState: AVCLAN_normalizeState(); diff --git a/src/avclandrv.h b/src/avclandrv.h index 44ca859..8d8907d 100644 --- a/src/avclandrv.h +++ b/src/avclandrv.h @@ -57,6 +57,7 @@ typedef enum : uint8_t { List_Functions_Req = 0x00, List_Functions_Resp = 0x10, Restart_Lan = 0x01, + // Lan_Startup_Complete = 0x58, Lancheck_End_Req = 0x08, Lancheck_End_Resp = 0x18, Lancheck_Scan_Req = 0x0a, @@ -77,34 +78,35 @@ typedef enum : uint8_t { Current_Function = 0x45, General_Query = 0x46, + // Events + Insertion = 0x50, + Ejection = 0x51, + // Physical interface Backlight_Adjust = 0x59, + Beep = 0x60, Eject = 0x80, Disc_Up = 0x90, Disc_Down = 0x91, - Pwrvol_Knob_Righthand_Turn = 0x9c, - Pwrvol_Knob_Lefthand_Turn = 0x9d, Track_Seek_Up = 0x94, Track_Seek_Down = 0x95, Track_Fast_Forward = 0x98, Track_Rewind = 0x99, - CD_Enable_Scan = 0xa6, - CD_Disable_Scan = 0xa7, - CD_Enable_Disk_Scan = 0xa9, - CD_Disable_Disk_Scan = 0xaa, + Pwrvol_Knob_Righthand_Turn = 0x9c, + Pwrvol_Knob_Lefthand_Turn = 0x9d, CD_Enable_Repeat = 0xa0, CD_Disable_Repeat = 0xa1, CD_Enable_Disk_Repeat = 0xa3, CD_Disable_Disk_Repeat = 0xa4, + CD_Enable_Scan = 0xa6, + CD_Disable_Scan = 0xa7, + CD_Enable_Disk_Scan = 0xa9, + CD_Disable_Disk_Scan = 0xaa, CD_Enable_Random = 0xb0, CD_Disable_Random = 0xb1, CD_Enable_Disk_Random = 0xb3, CD_Disable_Disk_Random = 0xb4, - // Events - Insertion = 0x50, - Ejection = 0x51, - // Requests and Response pairs Initial_Report_Request = 0xe0, Initial_Report_Response = 0xf0, @@ -164,6 +166,11 @@ typedef struct AVCLAN_CD_Status { typedef enum : uint8_t { stStop = 0, stPlay = 1 } cd_modes; +/// Message state machine +// - r_Nothing (0x00) means don't send current message +// - r_Handled means send current message and stop/finished state machine +// - All other instances mean send current message and imply the presence of +// follow-up messages within state machine typedef enum : uint8_t { r_Nothing = 0x00, r_Handled, // No follow-up needed @@ -172,6 +179,8 @@ typedef enum : uint8_t { r_StartPlaying, // started playing; send current status and then // normalize r_TrackChange, // Time needs reset + r_Ejection, + r_Report_Load, } response_t; typedef struct print_struct { diff --git a/src/sniffer.c b/src/sniffer.c index 7743eb2..117d927 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -237,12 +237,12 @@ int main() { out->controller_addr = DEVICE_ADDR; out->peripheral_addr = HU_ADDR; { - const uint8_t play[] = {0x00, dev_COMM_CTRL, dev_COMM_v1, - Insertion, dev_CD_CHANGER, 0x01}; + const uint8_t play[] = {0x00, dev_COMM_CTRL, dev_COMM_v1, + Ejection, dev_CD_CHANGER, 0x01}; out->length = sizeof(play); memcpy(out->data, play, sizeof(play)); } - *resp = (RFrame_t){.r = r_Handled, .frame = out}; + *resp = (RFrame_t){.r = r_Ejection, .frame = out}; push_or_return_resp(resp); } else pushQueue(&cache, out);