1*9f6d3c4bSStefan Richter #include <stdlib.h> 2*9f6d3c4bSStefan Richter #include <stdio.h> 3*9f6d3c4bSStefan Richter #include "list.h" 4*9f6d3c4bSStefan Richter #include "nosy-dump.h" 5*9f6d3c4bSStefan Richter 6*9f6d3c4bSStefan Richter #define CSR_FCP_COMMAND 0xfffff0000b00ull 7*9f6d3c4bSStefan Richter #define CSR_FCP_RESPONSE 0xfffff0000d00ull 8*9f6d3c4bSStefan Richter 9*9f6d3c4bSStefan Richter static const char * const ctype_names[16] = { 10*9f6d3c4bSStefan Richter "control", 11*9f6d3c4bSStefan Richter "status", 12*9f6d3c4bSStefan Richter "specific inquiry", 13*9f6d3c4bSStefan Richter "notify", 14*9f6d3c4bSStefan Richter "general inquiry", 15*9f6d3c4bSStefan Richter "(reserved 0x05)", 16*9f6d3c4bSStefan Richter "(reserved 0x06)", 17*9f6d3c4bSStefan Richter "(reserved 0x07)", 18*9f6d3c4bSStefan Richter "not implemented", 19*9f6d3c4bSStefan Richter "accepted", 20*9f6d3c4bSStefan Richter "rejected", 21*9f6d3c4bSStefan Richter "in transition", 22*9f6d3c4bSStefan Richter "stable", 23*9f6d3c4bSStefan Richter "changed", 24*9f6d3c4bSStefan Richter "(reserved 0x0e)", 25*9f6d3c4bSStefan Richter "interim" 26*9f6d3c4bSStefan Richter }; 27*9f6d3c4bSStefan Richter 28*9f6d3c4bSStefan Richter static const char * const subunit_type_names[32] = { 29*9f6d3c4bSStefan Richter "monitor", 30*9f6d3c4bSStefan Richter "audio", 31*9f6d3c4bSStefan Richter "printer", 32*9f6d3c4bSStefan Richter "disc", 33*9f6d3c4bSStefan Richter "tape recorder/player", 34*9f6d3c4bSStefan Richter "tuner", 35*9f6d3c4bSStefan Richter "ca", 36*9f6d3c4bSStefan Richter "camera", 37*9f6d3c4bSStefan Richter "(reserved 0x08)", 38*9f6d3c4bSStefan Richter "panel", 39*9f6d3c4bSStefan Richter "bulletin board", 40*9f6d3c4bSStefan Richter "camera storage", 41*9f6d3c4bSStefan Richter "(reserved 0x0c)", 42*9f6d3c4bSStefan Richter "(reserved 0x0d)", 43*9f6d3c4bSStefan Richter "(reserved 0x0e)", 44*9f6d3c4bSStefan Richter "(reserved 0x0f)", 45*9f6d3c4bSStefan Richter "(reserved 0x10)", 46*9f6d3c4bSStefan Richter "(reserved 0x11)", 47*9f6d3c4bSStefan Richter "(reserved 0x12)", 48*9f6d3c4bSStefan Richter "(reserved 0x13)", 49*9f6d3c4bSStefan Richter "(reserved 0x14)", 50*9f6d3c4bSStefan Richter "(reserved 0x15)", 51*9f6d3c4bSStefan Richter "(reserved 0x16)", 52*9f6d3c4bSStefan Richter "(reserved 0x17)", 53*9f6d3c4bSStefan Richter "(reserved 0x18)", 54*9f6d3c4bSStefan Richter "(reserved 0x19)", 55*9f6d3c4bSStefan Richter "(reserved 0x1a)", 56*9f6d3c4bSStefan Richter "(reserved 0x1b)", 57*9f6d3c4bSStefan Richter "vendor unique", 58*9f6d3c4bSStefan Richter "all subunit types", 59*9f6d3c4bSStefan Richter "subunit_type extended to next byte", 60*9f6d3c4bSStefan Richter "unit" 61*9f6d3c4bSStefan Richter }; 62*9f6d3c4bSStefan Richter 63*9f6d3c4bSStefan Richter struct avc_enum { 64*9f6d3c4bSStefan Richter int value; 65*9f6d3c4bSStefan Richter const char *name; 66*9f6d3c4bSStefan Richter }; 67*9f6d3c4bSStefan Richter 68*9f6d3c4bSStefan Richter struct avc_field { 69*9f6d3c4bSStefan Richter const char *name; /* Short name for field. */ 70*9f6d3c4bSStefan Richter int offset; /* Location of field, specified in bits. 71*9f6d3c4bSStefan Richter * Negative means from end of packet */ 72*9f6d3c4bSStefan Richter int width; /* Width of field, 0 means use data_length. */ 73*9f6d3c4bSStefan Richter struct avc_enum *names; 74*9f6d3c4bSStefan Richter }; 75*9f6d3c4bSStefan Richter 76*9f6d3c4bSStefan Richter struct avc_opcode_info { 77*9f6d3c4bSStefan Richter const char *name; 78*9f6d3c4bSStefan Richter struct avc_field fields[8]; 79*9f6d3c4bSStefan Richter }; 80*9f6d3c4bSStefan Richter 81*9f6d3c4bSStefan Richter struct avc_enum power_field_names[] = { 82*9f6d3c4bSStefan Richter { 0x70, "on" }, 83*9f6d3c4bSStefan Richter { 0x60, "off" }, 84*9f6d3c4bSStefan Richter { } 85*9f6d3c4bSStefan Richter }; 86*9f6d3c4bSStefan Richter 87*9f6d3c4bSStefan Richter static const struct avc_opcode_info opcode_info[256] = { 88*9f6d3c4bSStefan Richter 89*9f6d3c4bSStefan Richter /* TA Document 1999026 90*9f6d3c4bSStefan Richter * AV/C Digital Interface Command Set General Specification 91*9f6d3c4bSStefan Richter * Version 4.0 */ 92*9f6d3c4bSStefan Richter [0xb2] = 93*9f6d3c4bSStefan Richter { "power", { 94*9f6d3c4bSStefan Richter { "state", 0, 8, power_field_names } 95*9f6d3c4bSStefan Richter } 96*9f6d3c4bSStefan Richter }, 97*9f6d3c4bSStefan Richter [0x30] = 98*9f6d3c4bSStefan Richter { "unit info", { 99*9f6d3c4bSStefan Richter { "foo", 0, 8 }, 100*9f6d3c4bSStefan Richter { "unit_type", 8, 5 }, 101*9f6d3c4bSStefan Richter { "unit", 13, 3 }, 102*9f6d3c4bSStefan Richter { "company id", 16, 24 }, 103*9f6d3c4bSStefan Richter } 104*9f6d3c4bSStefan Richter }, 105*9f6d3c4bSStefan Richter [0x31] = { "subunit info" }, 106*9f6d3c4bSStefan Richter [0x01] = { "reserve" }, 107*9f6d3c4bSStefan Richter [0xb0] = { "version" }, 108*9f6d3c4bSStefan Richter [0x00] = { "vendor dependent" }, 109*9f6d3c4bSStefan Richter 110*9f6d3c4bSStefan Richter [0x02] = { "plug info" }, 111*9f6d3c4bSStefan Richter [0x12] = { "channel usage" }, 112*9f6d3c4bSStefan Richter [0x24] = { "connect" }, 113*9f6d3c4bSStefan Richter [0x20] = { "connect av" }, 114*9f6d3c4bSStefan Richter [0x22] = { "connections" }, 115*9f6d3c4bSStefan Richter [0x11] = { "digital input" }, 116*9f6d3c4bSStefan Richter [0x10] = { "digital output" }, 117*9f6d3c4bSStefan Richter [0x25] = { "disconnect" }, 118*9f6d3c4bSStefan Richter [0x21] = { "disconnect av" }, 119*9f6d3c4bSStefan Richter [0x19] = { "input plug signal format" }, 120*9f6d3c4bSStefan Richter [0x18] = { "output plug signal format" }, 121*9f6d3c4bSStefan Richter [0x1f] = { "general bus setup" }, 122*9f6d3c4bSStefan Richter 123*9f6d3c4bSStefan Richter /* TA Document 1999025 124*9f6d3c4bSStefan Richter * AV/C Descriptor Mechanism Specification Version 1.0 */ 125*9f6d3c4bSStefan Richter [0x0c] = { "create descriptor" }, 126*9f6d3c4bSStefan Richter [0x08] = { "open descriptor" }, 127*9f6d3c4bSStefan Richter [0x09] = { "read descriptor" }, 128*9f6d3c4bSStefan Richter [0x0a] = { "write descriptor" }, 129*9f6d3c4bSStefan Richter [0x05] = { "open info block" }, 130*9f6d3c4bSStefan Richter [0x06] = { "read info block" }, 131*9f6d3c4bSStefan Richter [0x07] = { "write info block" }, 132*9f6d3c4bSStefan Richter [0x0b] = { "search descriptor" }, 133*9f6d3c4bSStefan Richter [0x0d] = { "object number select" }, 134*9f6d3c4bSStefan Richter 135*9f6d3c4bSStefan Richter /* TA Document 1999015 136*9f6d3c4bSStefan Richter * AV/C Command Set for Rate Control of Isochronous Data Flow 1.0 */ 137*9f6d3c4bSStefan Richter [0xb3] = { "rate", { 138*9f6d3c4bSStefan Richter { "subfunction", 0, 8 }, 139*9f6d3c4bSStefan Richter { "result", 8, 8 }, 140*9f6d3c4bSStefan Richter { "plug_type", 16, 8 }, 141*9f6d3c4bSStefan Richter { "plug_id", 16, 8 }, 142*9f6d3c4bSStefan Richter } 143*9f6d3c4bSStefan Richter }, 144*9f6d3c4bSStefan Richter 145*9f6d3c4bSStefan Richter /* TA Document 1999008 146*9f6d3c4bSStefan Richter * AV/C Audio Subunit Specification 1.0 */ 147*9f6d3c4bSStefan Richter [0xb8] = { "function block" }, 148*9f6d3c4bSStefan Richter 149*9f6d3c4bSStefan Richter /* TA Document 2001001 150*9f6d3c4bSStefan Richter * AV/C Panel Subunit Specification 1.1 */ 151*9f6d3c4bSStefan Richter [0x7d] = { "gui update" }, 152*9f6d3c4bSStefan Richter [0x7e] = { "push gui data" }, 153*9f6d3c4bSStefan Richter [0x7f] = { "user action" }, 154*9f6d3c4bSStefan Richter [0x7c] = { "pass through" }, 155*9f6d3c4bSStefan Richter 156*9f6d3c4bSStefan Richter /* */ 157*9f6d3c4bSStefan Richter [0x26] = { "asynchronous connection" }, 158*9f6d3c4bSStefan Richter }; 159*9f6d3c4bSStefan Richter 160*9f6d3c4bSStefan Richter struct avc_frame { 161*9f6d3c4bSStefan Richter unsigned int operand0 : 8; 162*9f6d3c4bSStefan Richter unsigned int opcode : 8; 163*9f6d3c4bSStefan Richter unsigned int subunit_id : 3; 164*9f6d3c4bSStefan Richter unsigned int subunit_type : 5; 165*9f6d3c4bSStefan Richter unsigned int ctype : 4; 166*9f6d3c4bSStefan Richter unsigned int cts : 4; 167*9f6d3c4bSStefan Richter }; 168*9f6d3c4bSStefan Richter 169*9f6d3c4bSStefan Richter static void 170*9f6d3c4bSStefan Richter decode_avc(struct link_transaction *t) 171*9f6d3c4bSStefan Richter { 172*9f6d3c4bSStefan Richter struct avc_frame *frame = (struct avc_frame *) t->request->packet.write_block.data; 173*9f6d3c4bSStefan Richter const struct avc_opcode_info *info; 174*9f6d3c4bSStefan Richter const char *name; 175*9f6d3c4bSStefan Richter char buffer[32]; 176*9f6d3c4bSStefan Richter int i; 177*9f6d3c4bSStefan Richter 178*9f6d3c4bSStefan Richter info = &opcode_info[frame->opcode]; 179*9f6d3c4bSStefan Richter if (info->name == NULL) { 180*9f6d3c4bSStefan Richter snprintf(buffer, sizeof buffer, "(unknown opcode 0x%02x)", frame->opcode); 181*9f6d3c4bSStefan Richter name = buffer; 182*9f6d3c4bSStefan Richter } else { 183*9f6d3c4bSStefan Richter name = info->name; 184*9f6d3c4bSStefan Richter } 185*9f6d3c4bSStefan Richter 186*9f6d3c4bSStefan Richter printf("av/c %s, subunit_type=%s, subunit_id=%d, opcode=%s", 187*9f6d3c4bSStefan Richter ctype_names[frame->ctype], subunit_type_names[frame->subunit_type], 188*9f6d3c4bSStefan Richter frame->subunit_id, name); 189*9f6d3c4bSStefan Richter 190*9f6d3c4bSStefan Richter for (i = 0; info->fields[i].name != NULL; i++) { 191*9f6d3c4bSStefan Richter printf(", %s", info->fields[i].name); 192*9f6d3c4bSStefan Richter } 193*9f6d3c4bSStefan Richter 194*9f6d3c4bSStefan Richter printf("\n"); 195*9f6d3c4bSStefan Richter } 196*9f6d3c4bSStefan Richter 197*9f6d3c4bSStefan Richter 198*9f6d3c4bSStefan Richter int 199*9f6d3c4bSStefan Richter decode_fcp(struct link_transaction *t) 200*9f6d3c4bSStefan Richter { 201*9f6d3c4bSStefan Richter struct avc_frame *frame = (struct avc_frame *) t->request->packet.write_block.data; 202*9f6d3c4bSStefan Richter unsigned long long offset; 203*9f6d3c4bSStefan Richter 204*9f6d3c4bSStefan Richter offset = ((unsigned long long) t->request->packet.common.offset_high << 32) | 205*9f6d3c4bSStefan Richter t->request->packet.common.offset_low; 206*9f6d3c4bSStefan Richter 207*9f6d3c4bSStefan Richter if (t->request->packet.common.tcode != TCODE_WRITE_BLOCK) 208*9f6d3c4bSStefan Richter return 0; 209*9f6d3c4bSStefan Richter 210*9f6d3c4bSStefan Richter if (offset == CSR_FCP_COMMAND || offset == CSR_FCP_RESPONSE) { 211*9f6d3c4bSStefan Richter switch (frame->cts) { 212*9f6d3c4bSStefan Richter case 0x00: 213*9f6d3c4bSStefan Richter decode_avc(t); 214*9f6d3c4bSStefan Richter break; 215*9f6d3c4bSStefan Richter case 0x01: 216*9f6d3c4bSStefan Richter printf("cal fcp frame (cts=0x01)\n"); 217*9f6d3c4bSStefan Richter break; 218*9f6d3c4bSStefan Richter case 0x02: 219*9f6d3c4bSStefan Richter printf("ehs fcp frame (cts=0x02)\n"); 220*9f6d3c4bSStefan Richter break; 221*9f6d3c4bSStefan Richter case 0x03: 222*9f6d3c4bSStefan Richter printf("havi fcp frame (cts=0x03)\n"); 223*9f6d3c4bSStefan Richter break; 224*9f6d3c4bSStefan Richter case 0x0e: 225*9f6d3c4bSStefan Richter printf("vendor specific fcp frame (cts=0x0e)\n"); 226*9f6d3c4bSStefan Richter break; 227*9f6d3c4bSStefan Richter case 0x0f: 228*9f6d3c4bSStefan Richter printf("extended cts\n"); 229*9f6d3c4bSStefan Richter break; 230*9f6d3c4bSStefan Richter default: 231*9f6d3c4bSStefan Richter printf("reserved fcp frame (ctx=0x%02x)\n", frame->cts); 232*9f6d3c4bSStefan Richter break; 233*9f6d3c4bSStefan Richter } 234*9f6d3c4bSStefan Richter return 1; 235*9f6d3c4bSStefan Richter } 236*9f6d3c4bSStefan Richter 237*9f6d3c4bSStefan Richter return 0; 238*9f6d3c4bSStefan Richter } 239*9f6d3c4bSStefan Richter 240