1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <zircon/types.h>
6 #include <stdio.h>
7 
8 #include "intel_hda_codec.h"
9 #include "intel_hda_controller.h"
10 #include "zircon_device.h"
11 
12 namespace audio {
13 namespace intel_hda {
14 
GetController(int id)15 static IntelHDAController::ControllerTree::iterator GetController(int id) {
16     return (id < 0)
17         ? IntelHDAController::controllers().begin()
18         : IntelHDAController::controllers().find(id);
19 }
20 
GetCodec(int id)21 static IntelHDACodec::CodecTree::iterator GetCodec(int id) {
22     return (id < 0)
23         ? IntelHDACodec::codecs().begin()
24         : IntelHDACodec::codecs().find(id);
25 }
26 
main(int argc,const char ** argv)27 int main(int argc, const char** argv) {
28     int arg = 1;
29     int32_t dev_id = 0;
30     int32_t codec_id = 0;
31     zx_status_t res;
32 
33     while (arg < argc) {
34         if (!strcmp("-d", argv[arg])) {
35             if ((++arg >= argc) || sscanf(argv[arg++], "%d", &dev_id) != 1)
36                 goto usage;
37 
38             if (dev_id < 0)
39                 goto usage;
40         } else
41         if (!strcmp("-c", argv[arg])) {
42             if ((++arg >= argc) || sscanf(argv[arg++], "%d", &codec_id) != 1)
43                 goto usage;
44 
45             if (codec_id < 0)
46                 goto usage;
47         } else
48             break;
49     }
50 
51     if (arg >= argc)
52         goto usage;
53 
54     res = IntelHDAController::Enumerate();
55     if (res != ZX_OK) {
56         printf("Failed to enumerate controller devices (%d)\n", res);
57         return res;
58     }
59 
60     res = IntelHDACodec::Enumerate();
61     if (res != ZX_OK) {
62         printf("Failed to enumerate codec devices (%d)\n", res);
63         return res;
64     }
65 
66     if (!strcmp("list", argv[arg])) {
67         printf("Found %zu Intel HDA Controllers\n", IntelHDAController::controllers().size());
68         for (auto& controller : IntelHDAController::controllers()) {
69             res = controller.Probe();
70 
71             if (res != ZX_OK) {
72                 printf("Failed to probe controller at \"%s\" (res %d)\n",
73                         controller.dev_name(), res);
74                 return res;
75             }
76 
77             controller.Disconnect();
78 
79             printf("Controller %u [%04hx:%04hx %u.%u] : %s\n",
80                     controller.id(),
81                     controller.vid(),
82                     controller.did(),
83                     controller.ihda_vmaj(),
84                     controller.ihda_vmin(),
85                     controller.dev_name());
86         }
87 
88         printf("Found %zu Intel HDA Codecs\n", IntelHDACodec::codecs().size());
89         for (auto& codec : IntelHDACodec::codecs()) {
90             res = codec.Probe();
91 
92             if (res != ZX_OK) {
93                 printf("Failed to probe codec at \"%s\" (res %d)\n",
94                         codec.dev_name(), res);
95                 return res;
96             }
97 
98             printf("  Codec %u [%04hx:%04hx] : %s\n",
99                     codec.id(),
100                     codec.vid(),
101                     codec.did(),
102                     codec.dev_name());
103 
104             codec.Disconnect();
105         }
106 
107         return 0;
108     }
109 
110     static const struct {
111         const char* name;
112         zx_status_t (IntelHDAController::*cmd)(int, const char**);
113     } CONTROLLER_CMDS[] = {
114         { "regs",   &IntelHDAController::DumpRegs },
115     };
116 
117     for (const auto& cmd : CONTROLLER_CMDS) {
118         if (strcmp(cmd.name, argv[arg]))
119             continue;
120 
121         auto iter = GetController(dev_id);
122 
123         if (!iter.IsValid()) {
124             printf("Intel HDA controller not found!\n");
125             return ZX_ERR_NOT_FOUND;
126         }
127 
128         arg++;
129         return ((*iter).*cmd.cmd)(argc - arg, argv + arg);
130     }
131 
132     static const struct {
133         const char* name;
134         zx_status_t (IntelHDACodec::*cmd)(int, const char**);
135     } CODEC_CMDS[] = {
136         { "codec",   &IntelHDACodec::DumpCodec },
137     };
138 
139     for (const auto& cmd : CODEC_CMDS) {
140         if (strcmp(cmd.name, argv[arg]))
141             continue;
142 
143         auto iter = GetCodec(codec_id);
144 
145         if (!iter.IsValid()) {
146             printf("Intel HDA codec not found!\n");
147             return ZX_ERR_NOT_FOUND;
148         }
149 
150         arg++;
151         return ((*iter).*cmd.cmd)(argc - arg, argv + arg);
152     }
153 
154 usage:
155     printf("usage: %s [-d <dev_id>] [-c <codec_id>] <cmd>\n"
156            "Valid cmds are...\n"
157            "\thelp  : Show this message\n"
158            "\tlist  : List currently active devices and codecs.\n"
159            "\tregs  : Dump the registers for the specified device ID\n"
160            "\tcodec : Dump the internal structure of a codec\n",
161            argv[0]);
162 
163     return -1;
164 }
165 
166 }  // namespace audio
167 }  // namespace intel_hda
168 
main(int argc,const char ** argv)169 int main(int argc, const char** argv) {
170     return ::audio::intel_hda::main(argc, argv);
171 }
172