19f6d3c4bSStefan Richter #include <stdlib.h> 29f6d3c4bSStefan Richter #include <stdio.h> 39f6d3c4bSStefan Richter #include "list.h" 49f6d3c4bSStefan Richter #include "nosy-dump.h" 59f6d3c4bSStefan Richter 69f6d3c4bSStefan Richter #define CSR_FCP_COMMAND 0xfffff0000b00ull 79f6d3c4bSStefan Richter #define CSR_FCP_RESPONSE 0xfffff0000d00ull 89f6d3c4bSStefan Richter 9*92c16f7eSStefan Richter static const char * const ctype_names[] = { 10*92c16f7eSStefan Richter [0x0] = "control", [0x8] = "not implemented", 11*92c16f7eSStefan Richter [0x1] = "status", [0x9] = "accepted", 12*92c16f7eSStefan Richter [0x2] = "specific inquiry", [0xa] = "rejected", 13*92c16f7eSStefan Richter [0x3] = "notify", [0xb] = "in transition", 14*92c16f7eSStefan Richter [0x4] = "general inquiry", [0xc] = "stable", 15*92c16f7eSStefan Richter [0x5] = "(reserved 0x05)", [0xd] = "changed", 16*92c16f7eSStefan Richter [0x6] = "(reserved 0x06)", [0xe] = "(reserved 0x0e)", 17*92c16f7eSStefan Richter [0x7] = "(reserved 0x07)", [0xf] = "interim", 189f6d3c4bSStefan Richter }; 199f6d3c4bSStefan Richter 20*92c16f7eSStefan Richter static const char * const subunit_type_names[] = { 21*92c16f7eSStefan Richter [0x00] = "monitor", [0x10] = "(reserved 0x10)", 22*92c16f7eSStefan Richter [0x01] = "audio", [0x11] = "(reserved 0x11)", 23*92c16f7eSStefan Richter [0x02] = "printer", [0x12] = "(reserved 0x12)", 24*92c16f7eSStefan Richter [0x03] = "disc", [0x13] = "(reserved 0x13)", 25*92c16f7eSStefan Richter [0x04] = "tape recorder/player",[0x14] = "(reserved 0x14)", 26*92c16f7eSStefan Richter [0x05] = "tuner", [0x15] = "(reserved 0x15)", 27*92c16f7eSStefan Richter [0x06] = "ca", [0x16] = "(reserved 0x16)", 28*92c16f7eSStefan Richter [0x07] = "camera", [0x17] = "(reserved 0x17)", 29*92c16f7eSStefan Richter [0x08] = "(reserved 0x08)", [0x18] = "(reserved 0x18)", 30*92c16f7eSStefan Richter [0x09] = "panel", [0x19] = "(reserved 0x19)", 31*92c16f7eSStefan Richter [0x0a] = "bulletin board", [0x1a] = "(reserved 0x1a)", 32*92c16f7eSStefan Richter [0x0b] = "camera storage", [0x1b] = "(reserved 0x1b)", 33*92c16f7eSStefan Richter [0x0c] = "(reserved 0x0c)", [0x1c] = "vendor unique", 34*92c16f7eSStefan Richter [0x0d] = "(reserved 0x0d)", [0x1d] = "all subunit types", 35*92c16f7eSStefan Richter [0x0e] = "(reserved 0x0e)", [0x1e] = "subunit_type extended to next byte", 36*92c16f7eSStefan Richter [0x0f] = "(reserved 0x0f)", [0x1f] = "unit", 379f6d3c4bSStefan Richter }; 389f6d3c4bSStefan Richter 399f6d3c4bSStefan Richter struct avc_enum { 409f6d3c4bSStefan Richter int value; 419f6d3c4bSStefan Richter const char *name; 429f6d3c4bSStefan Richter }; 439f6d3c4bSStefan Richter 449f6d3c4bSStefan Richter struct avc_field { 459f6d3c4bSStefan Richter const char *name; /* Short name for field. */ 46*92c16f7eSStefan Richter int offset; /* Location of field, specified in bits; */ 47*92c16f7eSStefan Richter /* negative means from end of packet. */ 489f6d3c4bSStefan Richter int width; /* Width of field, 0 means use data_length. */ 499f6d3c4bSStefan Richter struct avc_enum *names; 509f6d3c4bSStefan Richter }; 519f6d3c4bSStefan Richter 529f6d3c4bSStefan Richter struct avc_opcode_info { 539f6d3c4bSStefan Richter const char *name; 549f6d3c4bSStefan Richter struct avc_field fields[8]; 559f6d3c4bSStefan Richter }; 569f6d3c4bSStefan Richter 579f6d3c4bSStefan Richter struct avc_enum power_field_names[] = { 589f6d3c4bSStefan Richter { 0x70, "on" }, 599f6d3c4bSStefan Richter { 0x60, "off" }, 609f6d3c4bSStefan Richter { } 619f6d3c4bSStefan Richter }; 629f6d3c4bSStefan Richter 639f6d3c4bSStefan Richter static const struct avc_opcode_info opcode_info[256] = { 649f6d3c4bSStefan Richter 65*92c16f7eSStefan Richter /* TA Document 1999026 */ 66*92c16f7eSStefan Richter /* AV/C Digital Interface Command Set General Specification 4.0 */ 67*92c16f7eSStefan Richter [0xb2] = { "power", { 689f6d3c4bSStefan Richter { "state", 0, 8, power_field_names } 699f6d3c4bSStefan Richter } 709f6d3c4bSStefan Richter }, 71*92c16f7eSStefan Richter [0x30] = { "unit info", { 729f6d3c4bSStefan Richter { "foo", 0, 8 }, 739f6d3c4bSStefan Richter { "unit_type", 8, 5 }, 749f6d3c4bSStefan Richter { "unit", 13, 3 }, 759f6d3c4bSStefan Richter { "company id", 16, 24 }, 769f6d3c4bSStefan Richter } 779f6d3c4bSStefan Richter }, 789f6d3c4bSStefan Richter [0x31] = { "subunit info" }, 799f6d3c4bSStefan Richter [0x01] = { "reserve" }, 809f6d3c4bSStefan Richter [0xb0] = { "version" }, 819f6d3c4bSStefan Richter [0x00] = { "vendor dependent" }, 829f6d3c4bSStefan Richter [0x02] = { "plug info" }, 839f6d3c4bSStefan Richter [0x12] = { "channel usage" }, 849f6d3c4bSStefan Richter [0x24] = { "connect" }, 859f6d3c4bSStefan Richter [0x20] = { "connect av" }, 869f6d3c4bSStefan Richter [0x22] = { "connections" }, 879f6d3c4bSStefan Richter [0x11] = { "digital input" }, 889f6d3c4bSStefan Richter [0x10] = { "digital output" }, 899f6d3c4bSStefan Richter [0x25] = { "disconnect" }, 909f6d3c4bSStefan Richter [0x21] = { "disconnect av" }, 919f6d3c4bSStefan Richter [0x19] = { "input plug signal format" }, 929f6d3c4bSStefan Richter [0x18] = { "output plug signal format" }, 939f6d3c4bSStefan Richter [0x1f] = { "general bus setup" }, 949f6d3c4bSStefan Richter 95*92c16f7eSStefan Richter /* TA Document 1999025 */ 96*92c16f7eSStefan Richter /* AV/C Descriptor Mechanism Specification Version 1.0 */ 979f6d3c4bSStefan Richter [0x0c] = { "create descriptor" }, 989f6d3c4bSStefan Richter [0x08] = { "open descriptor" }, 999f6d3c4bSStefan Richter [0x09] = { "read descriptor" }, 1009f6d3c4bSStefan Richter [0x0a] = { "write descriptor" }, 1019f6d3c4bSStefan Richter [0x05] = { "open info block" }, 1029f6d3c4bSStefan Richter [0x06] = { "read info block" }, 1039f6d3c4bSStefan Richter [0x07] = { "write info block" }, 1049f6d3c4bSStefan Richter [0x0b] = { "search descriptor" }, 1059f6d3c4bSStefan Richter [0x0d] = { "object number select" }, 1069f6d3c4bSStefan Richter 107*92c16f7eSStefan Richter /* TA Document 1999015 */ 108*92c16f7eSStefan Richter /* AV/C Command Set for Rate Control of Isochronous Data Flow 1.0 */ 1099f6d3c4bSStefan Richter [0xb3] = { "rate", { 1109f6d3c4bSStefan Richter { "subfunction", 0, 8 }, 1119f6d3c4bSStefan Richter { "result", 8, 8 }, 1129f6d3c4bSStefan Richter { "plug_type", 16, 8 }, 1139f6d3c4bSStefan Richter { "plug_id", 16, 8 }, 1149f6d3c4bSStefan Richter } 1159f6d3c4bSStefan Richter }, 1169f6d3c4bSStefan Richter 117*92c16f7eSStefan Richter /* TA Document 1999008 */ 118*92c16f7eSStefan Richter /* AV/C Audio Subunit Specification 1.0 */ 1199f6d3c4bSStefan Richter [0xb8] = { "function block" }, 1209f6d3c4bSStefan Richter 121*92c16f7eSStefan Richter /* TA Document 2001001 */ 122*92c16f7eSStefan Richter /* AV/C Panel Subunit Specification 1.1 */ 1239f6d3c4bSStefan Richter [0x7d] = { "gui update" }, 1249f6d3c4bSStefan Richter [0x7e] = { "push gui data" }, 1259f6d3c4bSStefan Richter [0x7f] = { "user action" }, 1269f6d3c4bSStefan Richter [0x7c] = { "pass through" }, 1279f6d3c4bSStefan Richter 1289f6d3c4bSStefan Richter /* */ 1299f6d3c4bSStefan Richter [0x26] = { "asynchronous connection" }, 1309f6d3c4bSStefan Richter }; 1319f6d3c4bSStefan Richter 1329f6d3c4bSStefan Richter struct avc_frame { 1331bcc69fbSStefan Richter uint32_t operand0:8; 1341bcc69fbSStefan Richter uint32_t opcode:8; 1351bcc69fbSStefan Richter uint32_t subunit_id:3; 1361bcc69fbSStefan Richter uint32_t subunit_type:5; 1371bcc69fbSStefan Richter uint32_t ctype:4; 1381bcc69fbSStefan Richter uint32_t cts:4; 1399f6d3c4bSStefan Richter }; 1409f6d3c4bSStefan Richter 1419f6d3c4bSStefan Richter static void 1429f6d3c4bSStefan Richter decode_avc(struct link_transaction *t) 1439f6d3c4bSStefan Richter { 144*92c16f7eSStefan Richter struct avc_frame *frame = 145*92c16f7eSStefan Richter (struct avc_frame *) t->request->packet.write_block.data; 1469f6d3c4bSStefan Richter const struct avc_opcode_info *info; 1479f6d3c4bSStefan Richter const char *name; 1489f6d3c4bSStefan Richter char buffer[32]; 1499f6d3c4bSStefan Richter int i; 1509f6d3c4bSStefan Richter 1519f6d3c4bSStefan Richter info = &opcode_info[frame->opcode]; 1529f6d3c4bSStefan Richter if (info->name == NULL) { 153*92c16f7eSStefan Richter snprintf(buffer, sizeof(buffer), 154*92c16f7eSStefan Richter "(unknown opcode 0x%02x)", frame->opcode); 1559f6d3c4bSStefan Richter name = buffer; 1569f6d3c4bSStefan Richter } else { 1579f6d3c4bSStefan Richter name = info->name; 1589f6d3c4bSStefan Richter } 1599f6d3c4bSStefan Richter 1609f6d3c4bSStefan Richter printf("av/c %s, subunit_type=%s, subunit_id=%d, opcode=%s", 1619f6d3c4bSStefan Richter ctype_names[frame->ctype], subunit_type_names[frame->subunit_type], 1629f6d3c4bSStefan Richter frame->subunit_id, name); 1639f6d3c4bSStefan Richter 164*92c16f7eSStefan Richter for (i = 0; info->fields[i].name != NULL; i++) 1659f6d3c4bSStefan Richter printf(", %s", info->fields[i].name); 1669f6d3c4bSStefan Richter 1679f6d3c4bSStefan Richter printf("\n"); 1689f6d3c4bSStefan Richter } 1699f6d3c4bSStefan Richter 1709f6d3c4bSStefan Richter int 1719f6d3c4bSStefan Richter decode_fcp(struct link_transaction *t) 1729f6d3c4bSStefan Richter { 173*92c16f7eSStefan Richter struct avc_frame *frame = 174*92c16f7eSStefan Richter (struct avc_frame *) t->request->packet.write_block.data; 175*92c16f7eSStefan Richter unsigned long long offset = 176*92c16f7eSStefan Richter ((unsigned long long) t->request->packet.common.offset_high << 32) | 1779f6d3c4bSStefan Richter t->request->packet.common.offset_low; 1789f6d3c4bSStefan Richter 1799f6d3c4bSStefan Richter if (t->request->packet.common.tcode != TCODE_WRITE_BLOCK) 1809f6d3c4bSStefan Richter return 0; 1819f6d3c4bSStefan Richter 1829f6d3c4bSStefan Richter if (offset == CSR_FCP_COMMAND || offset == CSR_FCP_RESPONSE) { 1839f6d3c4bSStefan Richter switch (frame->cts) { 1849f6d3c4bSStefan Richter case 0x00: 1859f6d3c4bSStefan Richter decode_avc(t); 1869f6d3c4bSStefan Richter break; 1879f6d3c4bSStefan Richter case 0x01: 1889f6d3c4bSStefan Richter printf("cal fcp frame (cts=0x01)\n"); 1899f6d3c4bSStefan Richter break; 1909f6d3c4bSStefan Richter case 0x02: 1919f6d3c4bSStefan Richter printf("ehs fcp frame (cts=0x02)\n"); 1929f6d3c4bSStefan Richter break; 1939f6d3c4bSStefan Richter case 0x03: 1949f6d3c4bSStefan Richter printf("havi fcp frame (cts=0x03)\n"); 1959f6d3c4bSStefan Richter break; 1969f6d3c4bSStefan Richter case 0x0e: 1979f6d3c4bSStefan Richter printf("vendor specific fcp frame (cts=0x0e)\n"); 1989f6d3c4bSStefan Richter break; 1999f6d3c4bSStefan Richter case 0x0f: 2009f6d3c4bSStefan Richter printf("extended cts\n"); 2019f6d3c4bSStefan Richter break; 2029f6d3c4bSStefan Richter default: 2039f6d3c4bSStefan Richter printf("reserved fcp frame (ctx=0x%02x)\n", frame->cts); 2049f6d3c4bSStefan Richter break; 2059f6d3c4bSStefan Richter } 2069f6d3c4bSStefan Richter return 1; 2079f6d3c4bSStefan Richter } 2089f6d3c4bSStefan Richter 2099f6d3c4bSStefan Richter return 0; 2109f6d3c4bSStefan Richter } 2119f6d3c4bSStefan Richter 212