1 /*
2  * Copyright (C) 2016 EPAM Systems Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; version 2.1 only. with the special
7  * exception on linking described in file LICENSE.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Lesser General Public License for more details.
13  */
14 
15 #include <stdlib.h>
16 
17 #include <libxl.h>
18 #include <libxl_utils.h>
19 #include <libxlutil.h>
20 
21 #include <xen/io/sndif.h>
22 
23 #include "xl.h"
24 #include "xl_utils.h"
25 #include "xl_parse.h"
26 
main_vsndattach(int argc,char ** argv)27 int main_vsndattach(int argc, char **argv)
28 {
29     int opt;
30     int rc;
31     uint32_t domid;
32     libxl_device_vsnd vsnd;
33 
34     SWITCH_FOREACH_OPT(opt, "", NULL, "vsnd-attach", 2) {
35         /* No options */
36     }
37 
38     libxl_device_vsnd_init(&vsnd);
39     domid = find_domain(argv[optind++]);
40 
41     for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
42         rc = parse_vsnd_item(&vsnd, *argv);
43         if (rc) goto out;
44     }
45 
46     if (dryrun_only) {
47         char *json = libxl_device_vsnd_to_json(ctx, &vsnd);
48         printf("vsnd: %s\n", json);
49         rc = 0;
50         free(json);
51         goto out;
52     }
53 
54     if (libxl_device_vsnd_add(ctx, domid, &vsnd, 0)) {
55         fprintf(stderr, "libxl_device_vsnd_add failed.\n");
56         rc = ERROR_FAIL; goto out;
57     }
58 
59     rc = 0;
60 
61 out:
62     libxl_device_vsnd_dispose(&vsnd);
63     return rc;
64 }
65 
print_params(libxl_vsnd_params * params)66 static void print_params(libxl_vsnd_params *params)
67 {
68     int i;
69 
70     if (params->channels_min) {
71         printf(", "XENSND_FIELD_CHANNELS_MIN": %u", params->channels_min);
72     }
73 
74     if (params->channels_max) {
75         printf(", "XENSND_FIELD_CHANNELS_MAX": %u", params->channels_max);
76     }
77 
78     if (params->buffer_size) {
79         printf(", "XENSND_FIELD_BUFFER_SIZE": %u", params->buffer_size);
80     }
81 
82     if (params->num_sample_rates) {
83         printf(", "XENSND_FIELD_SAMPLE_RATES": ");
84         for (i = 0; i < params->num_sample_rates - 1; i++) {
85             printf("%u;", params->sample_rates[i]);
86         }
87         printf("%u", params->sample_rates[i]);
88     }
89 
90     if (params->num_sample_formats) {
91         printf(", "XENSND_FIELD_SAMPLE_RATES": ");
92         for (i = 0; i < params->num_sample_formats - 1; i++) {
93             printf("%s;", libxl_vsnd_pcm_format_to_string(params->sample_formats[i]));
94         }
95         printf("%s", libxl_vsnd_pcm_format_to_string(params->sample_formats[i]));
96     }
97 
98     printf("\n");
99 }
100 
main_vsndlist(int argc,char ** argv)101 int main_vsndlist(int argc, char **argv)
102 {
103    int opt;
104    int i, j, k, n;
105    libxl_device_vsnd *vsnds;
106    libxl_vsndinfo vsndinfo;
107 
108    SWITCH_FOREACH_OPT(opt, "", NULL, "vsnd-list", 1) {
109        /* No options */
110    }
111 
112    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
113        uint32_t domid;
114 
115        if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
116            fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
117            continue;
118        }
119 
120        vsnds = libxl_device_vsnd_list(ctx, domid, &n);
121 
122        if (!vsnds) continue;
123 
124        for (i = 0; i < n; i++) {
125            libxl_vsndinfo_init(&vsndinfo);
126            if (libxl_device_vsnd_getinfo(ctx, domid, &vsnds[i],
127                                          &vsndinfo) == 0) {
128                printf("\ndevid: %d, be-domid: %d, handle: %d, state: %d, "
129                       "be-path: %s, fe-path: %s\n",
130                       vsndinfo.devid, vsndinfo.backend_id,
131                       vsndinfo.frontend_id, vsndinfo.state,
132                       vsndinfo.backend, vsndinfo.frontend);
133 
134                printf(XENSND_FIELD_VCARD_SHORT_NAME": \"%s\", "
135                       XENSND_FIELD_VCARD_LONG_NAME": \"%s\"",
136                       vsnds[i].short_name, vsnds[i].long_name);
137                print_params(&vsnds[i].params);
138 
139                for (j = 0; j < vsndinfo.num_vsnd_pcms; j++) {
140                    libxl_vsnd_pcm *pcm = &vsnds[i].pcms[j];
141 
142                    printf("\tpcm: %d, "XENSND_FIELD_DEVICE_NAME": \"%s\"", j, pcm->name);
143                    print_params(&pcm->params);
144 
145                    for(k = 0; k < vsnds[i].pcms[j].num_vsnd_streams; k++) {
146                        libxl_vsnd_stream *stream = &vsnds[i].pcms[j].streams[k];
147                        libxl_streaminfo *info = &vsndinfo.pcms[j].streams[k];
148 
149                        printf("\t\tstream: %d, "XENSND_FIELD_STREAM_UNIQUE_ID": \"%s\", "
150                               XENSND_FIELD_TYPE": %s", k, stream->unique_id,
151                               libxl_vsnd_stream_type_to_string(stream->type));
152                        print_params(&stream->params);
153                        printf("\t\t\t"XENSND_FIELD_EVT_CHNL": %d, "XENSND_FIELD_RING_REF": %d\n",
154                               info->req_evtch, info->req_rref);
155                    }
156                }
157            }
158            libxl_vsndinfo_dispose(&vsndinfo);
159        }
160        libxl_device_vsnd_list_free(vsnds, n);
161    }
162    return 0;
163 }
164 
main_vsnddetach(int argc,char ** argv)165 int main_vsnddetach(int argc, char **argv)
166 {
167     uint32_t domid, devid;
168     int opt, rc;
169     libxl_device_vsnd vsnd;
170 
171     SWITCH_FOREACH_OPT(opt, "", NULL, "vsnd-detach", 2) {
172         /* No options */
173     }
174 
175     domid = find_domain(argv[optind++]);
176     devid = atoi(argv[optind++]);
177 
178     libxl_device_vsnd_init(&vsnd);
179 
180     if (libxl_devid_to_device_vsnd(ctx, domid, devid, &vsnd)) {
181         fprintf(stderr, "Error: Device %d not connected.\n", devid);
182         rc = ERROR_FAIL;
183         goto out;
184     }
185 
186     rc = libxl_device_vsnd_remove(ctx, domid, &vsnd, 0);
187     if (rc) {
188         fprintf(stderr, "libxl_device_vsnd_remove failed.\n");
189         rc = ERROR_FAIL;
190         goto out;
191     }
192 
193     rc = 0;
194 
195 out:
196     libxl_device_vsnd_dispose(&vsnd);
197     return rc;
198 }
199 
200 
201 /*
202  * Local variables:
203  * mode: C
204  * c-basic-offset: 4
205  * indent-tabs-mode: nil
206  * End:
207  */
208