1 /** 2 * \file timer/timer_query.c 3 * \author Jaroslav Kysela <perex (at) perex.cz> 4 * \date 2001 5 * 6 * Timer Query Interface is designed to obtain identification of timers. 7 */ 8 /* 9 * Timer Query Interface - main file 10 * Copyright (c) 2001 by Jaroslav Kysela <perex (at) perex.cz> 11 * 12 * 13 * This library is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU Lesser General Public License as 15 * published by the Free Software Foundation; either version 2.1 of 16 * the License, or (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU Lesser General Public License for more details. 22 * 23 * You should have received a copy of the GNU Lesser General Public 24 * License along with this library; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26 * 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <string.h> 33 #include <fcntl.h> 34 #include <sys/ioctl.h> 35 #include "timer_local.h" 36 37 static int snd_timer_query_open_conf(snd_timer_query_t **timer, 38 const char *name, snd_config_t *timer_root, 39 snd_config_t *timer_conf, int mode) 40 { 41 const char *str; 42 char buf[256]; 43 int err; 44 snd_config_t *conf, *type_conf = NULL; 45 snd_config_iterator_t i, next; 46 const char *id; 47 const char *lib = NULL, *open_name = NULL; 48 int (*open_func)(snd_timer_query_t **, const char *, snd_config_t *, snd_config_t *, int) = NULL; 49 #ifndef PIC 50 extern void *snd_timer_query_open_symbols(void); 51 #endif 52 void *h = NULL; 53 if (snd_config_get_type(timer_conf) != SND_CONFIG_TYPE_COMPOUND) { 54 if (name) 55 SNDERR("Invalid type for TIMER %s definition", name); 56 else 57 SNDERR("Invalid type for TIMER definition"); 58 return -EINVAL; 59 } 60 err = snd_config_search(timer_conf, "type", &conf); 61 if (err < 0) { 62 SNDERR("type is not defined"); 63 return err; 64 } 65 err = snd_config_get_id(conf, &id); 66 if (err < 0) { 67 SNDERR("unable to get id"); 68 return err; 69 } 70 err = snd_config_get_string(conf, &str); 71 if (err < 0) { 72 SNDERR("Invalid type for %s", id); 73 return err; 74 } 75 err = snd_config_search_definition(timer_root, "timer_query_type", str, &type_conf); 76 if (err >= 0) { 77 if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) { 78 SNDERR("Invalid type for TIMER type %s definition", str); 79 err = -EINVAL; 80 goto _err; 81 } 82 snd_config_for_each(i, next, type_conf) { 83 snd_config_t *n = snd_config_iterator_entry(i); 84 const char *id; 85 if (snd_config_get_id(n, &id) < 0) 86 continue; 87 if (strcmp(id, "comment") == 0) 88 continue; 89 if (strcmp(id, "lib") == 0) { 90 err = snd_config_get_string(n, &lib); 91 if (err < 0) { 92 SNDERR("Invalid type for %s", id); 93 goto _err; 94 } 95 continue; 96 } 97 if (strcmp(id, "open") == 0) { 98 err = snd_config_get_string(n, &open_name); 99 if (err < 0) { 100 SNDERR("Invalid type for %s", id); 101 goto _err; 102 } 103 continue; 104 } 105 SNDERR("Unknown field %s", id); 106 err = -EINVAL; 107 goto _err; 108 } 109 } 110 if (!open_name) { 111 open_name = buf; 112 snprintf(buf, sizeof(buf), "_snd_timer_query_%s_open", str); 113 } 114 #ifndef PIC 115 snd_timer_query_open_symbols(); 116 #endif 117 h = snd_dlopen(lib, RTLD_NOW); 118 if (h) 119 open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_TIMER_QUERY_DLSYM_VERSION)); 120 err = 0; 121 if (!h) { 122 SNDERR("Cannot open shared library %s", lib); 123 err = -ENOENT; 124 } else if (!open_func) { 125 SNDERR("symbol %s is not defined inside %s", open_name, lib); 126 snd_dlclose(h); 127 err = -ENXIO; 128 } 129 _err: 130 if (type_conf) 131 snd_config_delete(type_conf); 132 if (! err) { 133 err = open_func(timer, name, timer_root, timer_conf, mode); 134 if (err < 0) 135 snd_dlclose(h); 136 else 137 (*timer)->dl_handle = h; 138 } 139 return err; 140 } 141 142 static int snd_timer_query_open_noupdate(snd_timer_query_t **timer, snd_config_t *root, const char *name, int mode) 143 { 144 int err; 145 snd_config_t *timer_conf; 146 err = snd_config_search_definition(root, "timer_query", name, &timer_conf); 147 if (err < 0) { 148 SNDERR("Unknown timer %s", name); 149 return err; 150 } 151 err = snd_timer_query_open_conf(timer, name, root, timer_conf, mode); 152 snd_config_delete(timer_conf); 153 return err; 154 } 155 156 /** 157 * \brief Opens a new connection to the timer query interface. 158 * \param timer Returned handle (NULL if not wanted) 159 * \param name ASCII identifier of the RawMidi handle 160 * \param mode Open mode 161 * \return 0 on success otherwise a negative error code 162 * 163 * Opens a new connection to the RawMidi interface specified with 164 * an ASCII identifier and mode. 165 */ 166 int snd_timer_query_open(snd_timer_query_t **timer, const char *name, int mode) 167 { 168 int err; 169 assert(timer && name); 170 err = snd_config_update(); 171 if (err < 0) 172 return err; 173 return snd_timer_query_open_noupdate(timer, snd_config, name, mode); 174 } 175 176 /** 177 * \brief Opens a new connection to the timer query interface using local configuration 178 * \param timer Returned handle (NULL if not wanted) 179 * \param name ASCII identifier of the RawMidi handle 180 * \param mode Open mode 181 * \param lconf Local configuration 182 * \return 0 on success otherwise a negative error code 183 * 184 * Opens a new connection to the RawMidi interface specified with 185 * an ASCII identifier and mode. 186 */ 187 int snd_timer_query_open_lconf(snd_timer_query_t **timer, const char *name, 188 int mode, snd_config_t *lconf) 189 { 190 assert(timer && name && lconf); 191 return snd_timer_query_open_noupdate(timer, lconf, name, mode); 192 } 193 194 /** 195 * \brief close timer query handle 196 * \param timer timer handle 197 * \return 0 on success otherwise a negative error code 198 * 199 * Closes the specified timer handle and frees all associated 200 * resources. 201 */ 202 int snd_timer_query_close(snd_timer_query_t *timer) 203 { 204 int err; 205 assert(timer); 206 err = timer->ops->close(timer); 207 if (timer->dl_handle) 208 snd_dlclose(timer->dl_handle); 209 free(timer->name); 210 free(timer); 211 return err; 212 } 213 214 /** 215 * \brief obtain the next timer identification 216 * \param timer timer handle 217 * \param tid timer identification 218 * \return 0 on success otherwise a negative error code 219 * 220 * if tid->dev_class is -1, then the first device is returned 221 * if result tid->dev_class is -1, no more devices are left 222 */ 223 int snd_timer_query_next_device(snd_timer_query_t *timer, snd_timer_id_t *tid) 224 { 225 assert(timer); 226 assert(tid); 227 return timer->ops->next_device(timer, tid); 228 } 229 230 /** 231 * \brief get size of the snd_timer_ginfo_t structure in bytes 232 * \return size of the snd_timer_ginfo_t structure in bytes 233 */ 234 size_t snd_timer_ginfo_sizeof(void) 235 { 236 return sizeof(snd_timer_ginfo_t); 237 } 238 239 /** 240 * \brief allocate a new snd_timer_ginfo_t structure 241 * \param info returned pointer 242 * \return 0 on success otherwise a negative error code if fails 243 * 244 * Allocates a new snd_timer_info_t structure using the standard 245 * malloc C library function. 246 */ 247 int snd_timer_ginfo_malloc(snd_timer_ginfo_t **info) 248 { 249 assert(info); 250 *info = calloc(1, sizeof(snd_timer_ginfo_t)); 251 if (!*info) 252 return -ENOMEM; 253 return 0; 254 } 255 256 /** 257 * \brief frees the snd_timer_ginfo_t structure 258 * \param info pointer to the snd_timer_ginfo_t structure to free 259 * 260 * Frees the given snd_timer_info_t structure using the standard 261 * free C library function. 262 */ 263 void snd_timer_ginfo_free(snd_timer_ginfo_t *info) 264 { 265 assert(info); 266 free(info); 267 } 268 269 /** 270 * \brief copy one snd_timer_info_t structure to another 271 * \param dst destination snd_timer_info_t structure 272 * \param src source snd_timer_info_t structure 273 */ 274 void snd_timer_ginfo_copy(snd_timer_ginfo_t *dst, const snd_timer_ginfo_t *src) 275 { 276 assert(dst && src); 277 *dst = *src; 278 } 279 280 /** 281 * \brief set timer identification 282 * \param obj pointer to #snd_timer_ginfo_t structure 283 * \param tid pointer to #snd_timer_id_t structure 284 * \return zero on success otherwise a negative error number 285 */ 286 int snd_timer_ginfo_set_tid(snd_timer_ginfo_t *obj, snd_timer_id_t *tid) 287 { 288 obj->tid = *((snd_timer_id_t *)tid); 289 return 0; 290 } 291 292 /** 293 * \brief get timer identification 294 * \param obj pointer to #snd_timer_ginfo_t structure 295 * \return pointer to snd_timer_id_t 296 */ 297 snd_timer_id_t *snd_timer_ginfo_get_tid(snd_timer_ginfo_t *obj) 298 { 299 return (snd_timer_id_t *)&obj->tid; 300 } 301 302 /** 303 * \brief get timer flags 304 * \param obj pointer to #snd_timer_ginfo_t structure 305 * \return timer flags 306 */ 307 unsigned int snd_timer_ginfo_get_flags(snd_timer_ginfo_t *obj) 308 { 309 return obj->flags; 310 } 311 312 /** 313 * \brief get associated card with timer 314 * \param obj pointer to #snd_timer_ginfo_t structure 315 * \return associated card 316 */ 317 int snd_timer_ginfo_get_card(snd_timer_ginfo_t *obj) 318 { 319 return obj->card; 320 } 321 322 /** 323 * \brief get timer identification 324 * \param obj pointer to #snd_timer_ginfo_t structure 325 * \return timer identification 326 */ 327 char *snd_timer_ginfo_get_id(snd_timer_ginfo_t *obj) 328 { 329 return (char *)obj->id; 330 } 331 332 /** 333 * \brief get timer name 334 * \param obj pointer to #snd_timer_ginfo_t structure 335 * \return timer name 336 */ 337 char *snd_timer_ginfo_get_name(snd_timer_ginfo_t *obj) 338 { 339 return (char *)obj->name; 340 } 341 342 /** 343 * \brief get timer resolution in ns 344 * \param obj pointer to #snd_timer_ginfo_t structure 345 * \return timer resolution in ns 346 */ 347 unsigned long snd_timer_ginfo_get_resolution(snd_timer_ginfo_t *obj) 348 { 349 return obj->resolution; 350 } 351 352 /** 353 * \brief get timer minimal resolution in ns 354 * \param obj pointer to #snd_timer_ginfo_t structure 355 * \return timer minimal resolution in ns 356 */ 357 unsigned long snd_timer_ginfo_get_resolution_min(snd_timer_ginfo_t *obj) 358 { 359 return obj->resolution_min; 360 } 361 362 /** 363 * \brief get timer maximal resolution in ns 364 * \param obj pointer to #snd_timer_ginfo_t structure 365 * \return timer maximal resolution in ns 366 */ 367 unsigned long snd_timer_ginfo_get_resolution_max(snd_timer_ginfo_t *obj) 368 { 369 return obj->resolution_max; 370 } 371 372 /** 373 * \brief get current timer clients 374 * \param obj pointer to #snd_timer_ginfo_t structure 375 * \return current timer clients 376 */ 377 unsigned int snd_timer_ginfo_get_clients(snd_timer_ginfo_t *obj) 378 { 379 return obj->clients; 380 } 381 382 /** 383 * \brief obtain the timer global information 384 * \param timer timer handle 385 * \param info timer information 386 * \return 0 on success otherwise a negative error code 387 */ 388 #ifndef DOXYGEN 389 int INTERNAL(snd_timer_query_info)(snd_timer_query_t *timer, snd_timer_ginfo_t *info) 390 #else 391 int snd_timer_query_info(snd_timer_query_t *timer, snd_timer_ginfo_t *info) 392 #endif 393 { 394 assert(timer); 395 assert(info); 396 return timer->ops->info(timer, info); 397 } 398 use_default_symbol_version(__snd_timer_query_info, snd_timer_query_info, ALSA_0.9.0); 399 400 /** 401 * \brief set the timer global parameters 402 * \param timer timer handle 403 * \param params timer parameters 404 * \return 0 on success otherwise a negative error code 405 */ 406 #ifndef DOXYGEN 407 int INTERNAL(snd_timer_query_params)(snd_timer_query_t *timer, snd_timer_gparams_t *params) 408 #else 409 int snd_timer_query_params(snd_timer_query_t *timer, snd_timer_gparams_t *params) 410 #endif 411 { 412 assert(timer); 413 assert(params); 414 return timer->ops->params(timer, params); 415 } 416 use_default_symbol_version(__snd_timer_query_params, snd_timer_query_params, ALSA_0.9.0); 417 418 /** 419 * \brief get the timer global status 420 * \param timer timer handle 421 * \param status timer status 422 * \return 0 on success otherwise a negative error code 423 */ 424 #ifndef DOXYGEN 425 int INTERNAL(snd_timer_query_status)(snd_timer_query_t *timer, snd_timer_gstatus_t *status) 426 #else 427 int snd_timer_query_status(snd_timer_query_t *timer, snd_timer_gstatus_t *status) 428 #endif 429 { 430 assert(timer); 431 assert(status); 432 return timer->ops->status(timer, status); 433 } 434 use_default_symbol_version(__snd_timer_query_status, snd_timer_query_status, ALSA_0.9.0); 435 436 /** 437 * \brief get size of the snd_timer_id_t structure in bytes 438 * \return size of the snd_timer_id_t structure in bytes 439 */ 440 size_t snd_timer_id_sizeof() 441 { 442 return sizeof(snd_timer_id_t); 443 } 444 445 /** 446 * \brief allocate a new snd_timer_id_t structure 447 * \param info returned pointer 448 * \return 0 on success otherwise a negative error code if fails 449 * 450 * Allocates a new snd_timer_id_t structure using the standard 451 * malloc C library function. 452 */ 453 int snd_timer_id_malloc(snd_timer_id_t **info) 454 { 455 assert(info); 456 *info = calloc(1, sizeof(snd_timer_id_t)); 457 if (!*info) 458 return -ENOMEM; 459 return 0; 460 } 461 462 /** 463 * \brief frees the snd_timer_id_t structure 464 * \param info pointer to the snd_timer_id_t structure to free 465 * 466 * Frees the given snd_timer_id_t structure using the standard 467 * free C library function. 468 */ 469 void snd_timer_id_free(snd_timer_id_t *info) 470 { 471 assert(info); 472 free(info); 473 } 474 475 /** 476 * \brief copy one snd_timer_id_t structure to another 477 * \param dst destination snd_timer_id_t structure 478 * \param src source snd_timer_id_t structure 479 */ 480 void snd_timer_id_copy(snd_timer_id_t *dst, const snd_timer_id_t *src) 481 { 482 assert(dst && src); 483 *dst = *src; 484 } 485 486 /** 487 * \brief set timer class 488 * \param tid pointer to #snd_timer_id_t structure 489 * \param dev_class class of timer device 490 */ 491 void snd_timer_id_set_class(snd_timer_id_t * tid, int dev_class) 492 { 493 assert(tid); 494 tid->dev_class = dev_class; 495 } 496 497 /** 498 * \brief get timer class 499 * \param tid pointer to #snd_timer_id_t structure 500 * \return timer class 501 */ 502 int snd_timer_id_get_class(snd_timer_id_t * tid) 503 { 504 assert(tid); 505 return tid->dev_class; 506 } 507 508 /** 509 * \brief set timer sub-class 510 * \param tid pointer to #snd_timer_id_t structure 511 * \param dev_sclass sub-class of timer device 512 */ 513 void snd_timer_id_set_sclass(snd_timer_id_t * tid, int dev_sclass) 514 { 515 assert(tid); 516 tid->dev_sclass = dev_sclass; 517 } 518 519 /** 520 * \brief get timer sub-class 521 * \param tid pointer to #snd_timer_id_t structure 522 * \return timer sub-class 523 */ 524 int snd_timer_id_get_sclass(snd_timer_id_t * tid) 525 { 526 assert(tid); 527 return tid->dev_sclass; 528 } 529 530 /** 531 * \brief set timer card 532 * \param tid pointer to #snd_timer_id_t structure 533 * \param card card number 534 */ 535 void snd_timer_id_set_card(snd_timer_id_t * tid, int card) 536 { 537 assert(tid); 538 tid->card = card; 539 } 540 541 /** 542 * \brief get timer card 543 * \param tid pointer to #snd_timer_id_t structure 544 * \return timer card number 545 */ 546 int snd_timer_id_get_card(snd_timer_id_t * tid) 547 { 548 assert(tid); 549 return tid->card; 550 } 551 552 /** 553 * \brief set timer device 554 * \param tid pointer to #snd_timer_id_t structure 555 * \param device device number 556 */ 557 void snd_timer_id_set_device(snd_timer_id_t * tid, int device) 558 { 559 assert(tid); 560 tid->device = device; 561 } 562 563 /** 564 * \brief get timer device 565 * \param tid pointer to #snd_timer_id_t structure 566 * \return timer device number 567 */ 568 int snd_timer_id_get_device(snd_timer_id_t * tid) 569 { 570 assert(tid); 571 return tid->device; 572 } 573 574 /** 575 * \brief set timer subdevice 576 * \param tid pointer to #snd_timer_id_t structure 577 * \param subdevice subdevice number 578 */ 579 void snd_timer_id_set_subdevice(snd_timer_id_t * tid, int subdevice) 580 { 581 assert(tid); 582 tid->subdevice = subdevice; 583 } 584 585 /** 586 * \brief get timer subdevice 587 * \param tid pointer to #snd_timer_id_t structure 588 * \return timer subdevice number 589 */ 590 int snd_timer_id_get_subdevice(snd_timer_id_t * tid) 591 { 592 assert(tid); 593 return tid->subdevice; 594 } 595