1 /* $NetBSD: hdaudioctl.c,v 1.1 2009/10/11 08:57:54 sborrill Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Precedence Technologies Ltd <support@precedence.co.uk> 5 * Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca> 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Precedence Technologies Ltd 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/types.h> 33 #include <sys/ioctl.h> 34 35 #include <prop/proplib.h> 36 37 #include <errno.h> 38 #include <fcntl.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <unistd.h> 43 #include <ctype.h> 44 45 #include <dev/pci/hdaudio/hdaudioio.h> 46 #include <dev/pci/hdaudio/hdaudioreg.h> 47 48 #include "hdaudioctl.h" 49 50 #define DEVPATH_HDAUDIO "/dev/hdaudio0" 51 52 void 53 usage(void) 54 { 55 const char *prog; 56 prog = getprogname(); 57 58 fprintf(stderr, "usage: %s [-f dev] list\n", prog); 59 fprintf(stderr, " %s [-f dev] get <codecid> <nid>\n", prog); 60 fprintf(stderr, " %s [-f dev] set <codecid> <nid> [plist]\n", 61 prog); 62 fprintf(stderr, " %s [-f dev] graph <codecid> <nid>\n", prog); 63 exit(EXIT_FAILURE); 64 } 65 66 static int 67 hdaudioctl_list(int fd) 68 { 69 prop_dictionary_t request, response; 70 prop_dictionary_t dict; 71 prop_object_iterator_t iter; 72 prop_object_t obj; 73 prop_array_t array; 74 uint16_t nid, codecid; 75 uint16_t vendor, product; 76 uint32_t subsystem; 77 const char *device = NULL; 78 int error; 79 80 request = prop_dictionary_create(); 81 if (request == NULL) { 82 fprintf(stderr, "out of memory\n"); 83 return ENOMEM; 84 } 85 86 error = prop_dictionary_sendrecv_ioctl(request, fd, 87 HDAUDIO_FGRP_INFO, &response); 88 if (error != 0) { 89 perror("HDAUDIO_FGRP_INFO failed"); 90 return error; 91 } 92 93 array = prop_dictionary_get(response, "function-group-info"); 94 iter = prop_array_iterator(array); 95 prop_object_iterator_reset(iter); 96 while ((obj = prop_object_iterator_next(iter)) != NULL) { 97 dict = (prop_dictionary_t)obj; 98 prop_dictionary_get_uint16(dict, "codecid", &codecid); 99 prop_dictionary_get_uint16(dict, "nid", &nid); 100 prop_dictionary_get_uint16(dict, "vendor-id", &vendor); 101 prop_dictionary_get_uint16(dict, "product-id", &product); 102 prop_dictionary_get_uint32(dict, "subsystem-id", &subsystem); 103 prop_dictionary_get_cstring_nocopy(dict, "device", &device); 104 105 printf("codecid 0x%02X nid 0x%02X vendor 0x%04X " 106 "product 0x%04X subsystem 0x%08X device %s\n", 107 codecid, nid, vendor, product, subsystem, 108 device ? device : "<none>"); 109 } 110 111 prop_object_release(array); 112 prop_object_release(response); 113 prop_object_release(request); 114 115 return 0; 116 } 117 118 static int 119 hdaudioctl_get(int fd, int argc, char *argv[]) 120 { 121 prop_dictionary_t request, response; 122 prop_array_t config; 123 uint16_t nid, codecid; 124 const char *xml; 125 int error; 126 127 if (argc != 2) 128 usage(); 129 130 codecid = strtol(argv[0], NULL, 0); 131 nid = strtol(argv[1], NULL, 0); 132 133 request = prop_dictionary_create(); 134 if (request == NULL) { 135 fprintf(stderr, "out of memory\n"); 136 return ENOMEM; 137 } 138 139 prop_dictionary_set_uint16(request, "codecid", codecid); 140 prop_dictionary_set_uint16(request, "nid", nid); 141 142 error = prop_dictionary_sendrecv_ioctl(request, fd, 143 HDAUDIO_FGRP_GETCONFIG, &response); 144 if (error != 0) { 145 perror("HDAUDIO_FGRP_GETCONFIG failed"); 146 return error; 147 } 148 149 config = prop_dictionary_get(response, "pin-config"); 150 xml = prop_array_externalize(config); 151 152 printf("%s\n", xml); 153 154 prop_object_release(response); 155 prop_object_release(request); 156 157 return 0; 158 } 159 160 static int 161 hdaudioctl_set(int fd, int argc, char *argv[]) 162 { 163 prop_dictionary_t request, response; 164 prop_array_t config = NULL; 165 uint16_t nid, codecid; 166 int error; 167 168 if (argc < 2 || argc > 3) 169 usage(); 170 171 codecid = strtol(argv[0], NULL, 0); 172 nid = strtol(argv[1], NULL, 0); 173 if (argc == 3) { 174 config = prop_array_internalize_from_file(argv[2]); 175 if (config == NULL) { 176 fprintf(stderr, 177 "couldn't load configuration from %s\n", argv[2]); 178 return EIO; 179 } 180 } 181 182 request = prop_dictionary_create(); 183 if (request == NULL) { 184 fprintf(stderr, "out of memory\n"); 185 return ENOMEM; 186 } 187 188 prop_dictionary_set_uint16(request, "codecid", codecid); 189 prop_dictionary_set_uint16(request, "nid", nid); 190 if (config) 191 prop_dictionary_set(request, "pin-config", config); 192 193 error = prop_dictionary_sendrecv_ioctl(request, fd, 194 HDAUDIO_FGRP_SETCONFIG, &response); 195 if (error != 0) { 196 perror("HDAUDIO_FGRP_SETCONFIG failed"); 197 return error; 198 } 199 200 prop_object_release(response); 201 prop_object_release(request); 202 203 return 0; 204 } 205 206 207 int 208 main(int argc, char *argv[]) 209 { 210 int fd, error; 211 int ch; 212 const char *devpath = DEVPATH_HDAUDIO; 213 214 while ((ch = getopt(argc, argv, "f:h")) != -1) { 215 switch (ch) { 216 case 'f': 217 devpath = strdup(optarg); 218 break; 219 case 'h': 220 default: 221 usage(); 222 /* NOTREACHED */ 223 } 224 } 225 argc -= optind; 226 argv += optind; 227 228 if (argc < 1) 229 usage(); 230 231 fd = open(devpath, O_RDWR); 232 if (fd < 0) { 233 fprintf(stderr, "Error opening %s: %s\n", devpath, 234 strerror(errno)); 235 return EXIT_FAILURE; 236 } 237 238 error = 0; 239 if (strcmp(argv[0], "list") == 0) 240 error = hdaudioctl_list(fd); 241 else if (strcmp(argv[0], "get") == 0) 242 error = hdaudioctl_get(fd, argc - 1, argv + 1); 243 else if (strcmp(argv[0], "set") == 0) 244 error = hdaudioctl_set(fd, argc - 1, argv + 1); 245 else if (strcmp(argv[0], "graph") == 0) 246 error = hdaudioctl_graph(fd, argc - 1, argv + 1); 247 else 248 usage(); 249 250 close(fd); 251 252 if (error) 253 return EXIT_FAILURE; 254 return EXIT_SUCCESS; 255 } 256