1/* SPDX-License-Identifier: GPL-2.0-only */ 2package decoder 3 4import ( 5 "fmt" 6 "math/bits" 7) 8 9type Fields[T uint32 | string] struct { 10 PortConnectivity T 11 Location T 12 DefaultDevice T 13 ConnectionType T 14 Color T 15 Misc T 16 DefaultAssociation T 17 Sequence T 18} 19 20func getField(config uint32, mask uint32) uint32 { 21 return (config & mask) >> bits.TrailingZeros32(mask) 22} 23 24func Decode(config uint32) Fields[uint32] { 25 return Fields[uint32]{ 26 PortConnectivity: getField(config, 0xc0000000), 27 Location: getField(config, 0x3f000000), 28 DefaultDevice: getField(config, 0x00f00000), 29 ConnectionType: getField(config, 0x000f0000), 30 Color: getField(config, 0x0000f000), 31 Misc: getField(config, 0x00000f00), 32 DefaultAssociation: getField(config, 0x000000f0), 33 Sequence: getField(config, 0x0000000f), 34 } 35} 36 37func PortIsConnected(config uint32) bool { 38 return Decode(config).PortConnectivity != 0x1 39} 40 41var portConnectivityDescriptions = map[uint32]string{ 42 0x0: "AZALIA_JACK", 43 0x1: "AZALIA_NC", 44 0x2: "AZALIA_INTEGRATED", 45 0x3: "AZALIA_JACK_AND_INTEGRATED", 46} 47 48var grossLocationDescriptions = map[uint32]string{ 49 0x00: "AZALIA_EXTERNAL_PRIMARY_CHASSIS", 50 0x10: "AZALIA_INTERNAL", 51 0x20: "AZALIA_SEPARATE_CHASSIS", 52 0x30: "AZALIA_LOCATION_OTHER", 53} 54 55var geometricLocationDescriptions = map[uint32]string{ 56 0x00: "AZALIA_GEOLOCATION_NA", 57 0x01: "AZALIA_REAR", 58 0x02: "AZALIA_FRONT", 59 0x03: "AZALIA_LEFT", 60 0x04: "AZALIA_RIGHT", 61 0x05: "AZALIA_TOP", 62 0x06: "AZALIA_BOTTOM", 63 0x07: "AZALIA_SPECIAL7", 64 0x08: "AZALIA_SPECIAL8", 65 0x09: "AZALIA_SPECIAL9", 66} 67 68var specialLocationDescriptions = map[uint32]string{ 69 0x00 | 0x07: "AZALIA_REAR_PANEL", 70 0x00 | 0x08: "AZALIA_DRIVE_BAY", 71 0x10 | 0x07: "AZALIA_RISER", 72 0x10 | 0x08: "AZALIA_DIGITAL_DISPLAY", 73 0x10 | 0x09: "AZALIA_ATAPI", 74 0x30 | 0x07: "AZALIA_MOBILE_LID_INSIDE", 75 0x30 | 0x08: "AZALIA_MOBILE_LID_OUTSIDE", 76} 77 78var defaultDeviceDescriptions = map[uint32]string{ 79 0x0: "AZALIA_LINE_OUT", 80 0x1: "AZALIA_SPEAKER", 81 0x2: "AZALIA_HP_OUT", 82 0x3: "AZALIA_CD", 83 0x4: "AZALIA_SPDIF_OUT", 84 0x5: "AZALIA_DIGITAL_OTHER_OUT", 85 0x6: "AZALIA_MODEM_LINE_SIDE", 86 0x7: "AZALIA_MODEM_HANDSET_SIDE", 87 0x8: "AZALIA_LINE_IN", 88 0x9: "AZALIA_AUX", 89 0xa: "AZALIA_MIC_IN", 90 0xb: "AZALIA_TELEPHONY", 91 0xc: "AZALIA_SPDIF_IN", 92 0xd: "AZALIA_DIGITAL_OTHER_IN", 93 0xf: "AZALIA_DEVICE_OTHER", 94} 95 96var connectionTypeDescriptions = map[uint32]string{ 97 0x0: "AZALIA_TYPE_UNKNOWN", 98 0x1: "AZALIA_STEREO_MONO_1_8", 99 0x2: "AZALIA_STEREO_MONO_1_4", 100 0x3: "AZALIA_ATAPI_INTERNAL", 101 0x4: "AZALIA_RCA", 102 0x5: "AZALIA_OPTICAL", 103 0x6: "AZALIA_OTHER_DIGITAL", 104 0x7: "AZALIA_OTHER_ANALOG", 105 0x8: "AZALIA_MULTICHANNEL_ANALOG", 106 0x9: "AZALIA_XLR", 107 0xa: "AZALIA_RJ_11", 108 0xb: "AZALIA_COMBINATION", 109 0xf: "AZALIA_TYPE_OTHER", 110} 111 112var colorDescriptions = map[uint32]string{ 113 0x0: "AZALIA_COLOR_UNKNOWN", 114 0x1: "AZALIA_BLACK", 115 0x2: "AZALIA_GREY", 116 0x3: "AZALIA_BLUE", 117 0x4: "AZALIA_GREEN", 118 0x5: "AZALIA_RED", 119 0x6: "AZALIA_ORANGE", 120 0x7: "AZALIA_YELLOW", 121 0x8: "AZALIA_PURPLE", 122 0x9: "AZALIA_PINK", 123 0xe: "AZALIA_WHITE", 124 0xf: "AZALIA_COLOR_OTHER", 125} 126 127var miscDescriptions = map[uint32]string{ 128 0x0: "AZALIA_JACK_PRESENCE_DETECT", 129 0x1: "AZALIA_NO_JACK_PRESENCE_DETECT", 130} 131 132func getDescription(field uint32, descriptions map[uint32]string) string { 133 desc, exists := descriptions[field] 134 135 if !exists { 136 return fmt.Sprintf("0x%x", field) 137 } 138 return desc 139} 140 141func getLocationDescription(field uint32) string { 142 desc, isSpecialLocation := specialLocationDescriptions[field] 143 if isSpecialLocation { 144 return desc 145 } 146 147 grossLocation := field & 0x30 148 geometricLocation := field & 0x0f 149 150 desc = grossLocationDescriptions[grossLocation] 151 if geometricLocation != 0x00 { 152 desc += " | " + getDescription(geometricLocation, geometricLocationDescriptions) 153 } 154 return desc 155} 156 157func getMiscDescription(field uint32) string { 158 presenceBit := field & 0b0001 159 reservedBits := field & 0b1110 160 161 desc := miscDescriptions[presenceBit] 162 if bits.OnesCount32(reservedBits) > 0 { 163 desc += fmt.Sprintf(" | 0x%x", reservedBits) 164 } 165 return desc 166} 167 168func ToHumanReadable(fields Fields[uint32]) Fields[string] { 169 return Fields[string]{ 170 PortConnectivity: getDescription(fields.PortConnectivity, portConnectivityDescriptions), 171 Location: getLocationDescription(fields.Location), 172 DefaultDevice: getDescription(fields.DefaultDevice, defaultDeviceDescriptions), 173 ConnectionType: getDescription(fields.ConnectionType, connectionTypeDescriptions), 174 Color: getDescription(fields.Color, colorDescriptions), 175 Misc: getMiscDescription(fields.Misc), 176 DefaultAssociation: fmt.Sprintf("%d", fields.DefaultAssociation), 177 Sequence: fmt.Sprintf("%d", fields.Sequence), 178 } 179} 180