1 /* 2 * Routines for driver control interface 3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz> 4 * 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21 22 #include <sound/driver.h> 23 #include <linux/threads.h> 24 #include <linux/interrupt.h> 25 #include <linux/smp_lock.h> 26 #include <linux/slab.h> 27 #include <linux/vmalloc.h> 28 #include <linux/time.h> 29 #include <sound/core.h> 30 #include <sound/minors.h> 31 #include <sound/info.h> 32 #include <sound/control.h> 33 34 /* max number of user-defined controls */ 35 #define MAX_USER_CONTROLS 32 36 37 typedef struct _snd_kctl_ioctl { 38 struct list_head list; /* list of all ioctls */ 39 snd_kctl_ioctl_func_t fioctl; 40 } snd_kctl_ioctl_t; 41 42 #define snd_kctl_ioctl(n) list_entry(n, snd_kctl_ioctl_t, list) 43 44 static DECLARE_RWSEM(snd_ioctl_rwsem); 45 static LIST_HEAD(snd_control_ioctls); 46 #ifdef CONFIG_COMPAT 47 static LIST_HEAD(snd_control_compat_ioctls); 48 #endif 49 50 static int snd_ctl_open(struct inode *inode, struct file *file) 51 { 52 int cardnum = SNDRV_MINOR_CARD(iminor(inode)); 53 unsigned long flags; 54 snd_card_t *card; 55 snd_ctl_file_t *ctl; 56 int err; 57 58 card = snd_cards[cardnum]; 59 if (!card) { 60 err = -ENODEV; 61 goto __error1; 62 } 63 err = snd_card_file_add(card, file); 64 if (err < 0) { 65 err = -ENODEV; 66 goto __error1; 67 } 68 if (!try_module_get(card->module)) { 69 err = -EFAULT; 70 goto __error2; 71 } 72 ctl = kcalloc(1, sizeof(*ctl), GFP_KERNEL); 73 if (ctl == NULL) { 74 err = -ENOMEM; 75 goto __error; 76 } 77 INIT_LIST_HEAD(&ctl->events); 78 init_waitqueue_head(&ctl->change_sleep); 79 spin_lock_init(&ctl->read_lock); 80 ctl->card = card; 81 ctl->pid = current->pid; 82 file->private_data = ctl; 83 write_lock_irqsave(&card->ctl_files_rwlock, flags); 84 list_add_tail(&ctl->list, &card->ctl_files); 85 write_unlock_irqrestore(&card->ctl_files_rwlock, flags); 86 return 0; 87 88 __error: 89 module_put(card->module); 90 __error2: 91 snd_card_file_remove(card, file); 92 __error1: 93 return err; 94 } 95 96 static void snd_ctl_empty_read_queue(snd_ctl_file_t * ctl) 97 { 98 snd_kctl_event_t *cread; 99 100 spin_lock(&ctl->read_lock); 101 while (!list_empty(&ctl->events)) { 102 cread = snd_kctl_event(ctl->events.next); 103 list_del(&cread->list); 104 kfree(cread); 105 } 106 spin_unlock(&ctl->read_lock); 107 } 108 109 static int snd_ctl_release(struct inode *inode, struct file *file) 110 { 111 unsigned long flags; 112 struct list_head *list; 113 snd_card_t *card; 114 snd_ctl_file_t *ctl; 115 snd_kcontrol_t *control; 116 unsigned int idx; 117 118 ctl = file->private_data; 119 fasync_helper(-1, file, 0, &ctl->fasync); 120 file->private_data = NULL; 121 card = ctl->card; 122 write_lock_irqsave(&card->ctl_files_rwlock, flags); 123 list_del(&ctl->list); 124 write_unlock_irqrestore(&card->ctl_files_rwlock, flags); 125 down_write(&card->controls_rwsem); 126 list_for_each(list, &card->controls) { 127 control = snd_kcontrol(list); 128 for (idx = 0; idx < control->count; idx++) 129 if (control->vd[idx].owner == ctl) 130 control->vd[idx].owner = NULL; 131 } 132 up_write(&card->controls_rwsem); 133 snd_ctl_empty_read_queue(ctl); 134 kfree(ctl); 135 module_put(card->module); 136 snd_card_file_remove(card, file); 137 return 0; 138 } 139 140 void snd_ctl_notify(snd_card_t *card, unsigned int mask, snd_ctl_elem_id_t *id) 141 { 142 unsigned long flags; 143 struct list_head *flist; 144 snd_ctl_file_t *ctl; 145 snd_kctl_event_t *ev; 146 147 snd_runtime_check(card != NULL && id != NULL, return); 148 read_lock(&card->ctl_files_rwlock); 149 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) 150 card->mixer_oss_change_count++; 151 #endif 152 list_for_each(flist, &card->ctl_files) { 153 struct list_head *elist; 154 ctl = snd_ctl_file(flist); 155 if (!ctl->subscribed) 156 continue; 157 spin_lock_irqsave(&ctl->read_lock, flags); 158 list_for_each(elist, &ctl->events) { 159 ev = snd_kctl_event(elist); 160 if (ev->id.numid == id->numid) { 161 ev->mask |= mask; 162 goto _found; 163 } 164 } 165 ev = kcalloc(1, sizeof(*ev), GFP_ATOMIC); 166 if (ev) { 167 ev->id = *id; 168 ev->mask = mask; 169 list_add_tail(&ev->list, &ctl->events); 170 } else { 171 snd_printk(KERN_ERR "No memory available to allocate event\n"); 172 } 173 _found: 174 wake_up(&ctl->change_sleep); 175 spin_unlock_irqrestore(&ctl->read_lock, flags); 176 kill_fasync(&ctl->fasync, SIGIO, POLL_IN); 177 } 178 read_unlock(&card->ctl_files_rwlock); 179 } 180 181 /** 182 * snd_ctl_new - create a control instance from the template 183 * @control: the control template 184 * @access: the default control access 185 * 186 * Allocates a new snd_kcontrol_t instance and copies the given template 187 * to the new instance. It does not copy volatile data (access). 188 * 189 * Returns the pointer of the new instance, or NULL on failure. 190 */ 191 snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control, unsigned int access) 192 { 193 snd_kcontrol_t *kctl; 194 unsigned int idx; 195 196 snd_runtime_check(control != NULL, return NULL); 197 snd_runtime_check(control->count > 0, return NULL); 198 kctl = kcalloc(1, sizeof(*kctl) + sizeof(snd_kcontrol_volatile_t) * control->count, GFP_KERNEL); 199 if (kctl == NULL) 200 return NULL; 201 *kctl = *control; 202 for (idx = 0; idx < kctl->count; idx++) 203 kctl->vd[idx].access = access; 204 return kctl; 205 } 206 207 /** 208 * snd_ctl_new1 - create a control instance from the template 209 * @ncontrol: the initialization record 210 * @private_data: the private data to set 211 * 212 * Allocates a new snd_kcontrol_t instance and initialize from the given 213 * template. When the access field of ncontrol is 0, it's assumed as 214 * READWRITE access. When the count field is 0, it's assumes as one. 215 * 216 * Returns the pointer of the newly generated instance, or NULL on failure. 217 */ 218 snd_kcontrol_t *snd_ctl_new1(snd_kcontrol_new_t * ncontrol, void *private_data) 219 { 220 snd_kcontrol_t kctl; 221 unsigned int access; 222 223 snd_runtime_check(ncontrol != NULL, return NULL); 224 snd_assert(ncontrol->info != NULL, return NULL); 225 memset(&kctl, 0, sizeof(kctl)); 226 kctl.id.iface = ncontrol->iface; 227 kctl.id.device = ncontrol->device; 228 kctl.id.subdevice = ncontrol->subdevice; 229 if (ncontrol->name) 230 strlcpy(kctl.id.name, ncontrol->name, sizeof(kctl.id.name)); 231 kctl.id.index = ncontrol->index; 232 kctl.count = ncontrol->count ? ncontrol->count : 1; 233 access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : 234 (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|SNDRV_CTL_ELEM_ACCESS_INACTIVE| 235 SNDRV_CTL_ELEM_ACCESS_DINDIRECT|SNDRV_CTL_ELEM_ACCESS_INDIRECT)); 236 kctl.info = ncontrol->info; 237 kctl.get = ncontrol->get; 238 kctl.put = ncontrol->put; 239 kctl.private_value = ncontrol->private_value; 240 kctl.private_data = private_data; 241 return snd_ctl_new(&kctl, access); 242 } 243 244 /** 245 * snd_ctl_free_one - release the control instance 246 * @kcontrol: the control instance 247 * 248 * Releases the control instance created via snd_ctl_new() 249 * or snd_ctl_new1(). 250 * Don't call this after the control was added to the card. 251 */ 252 void snd_ctl_free_one(snd_kcontrol_t * kcontrol) 253 { 254 if (kcontrol) { 255 if (kcontrol->private_free) 256 kcontrol->private_free(kcontrol); 257 kfree(kcontrol); 258 } 259 } 260 261 static unsigned int snd_ctl_hole_check(snd_card_t * card, 262 unsigned int count) 263 { 264 struct list_head *list; 265 snd_kcontrol_t *kctl; 266 267 list_for_each(list, &card->controls) { 268 kctl = snd_kcontrol(list); 269 if ((kctl->id.numid <= card->last_numid && 270 kctl->id.numid + kctl->count > card->last_numid) || 271 (kctl->id.numid <= card->last_numid + count - 1 && 272 kctl->id.numid + kctl->count > card->last_numid + count - 1)) 273 return card->last_numid = kctl->id.numid + kctl->count - 1; 274 } 275 return card->last_numid; 276 } 277 278 static int snd_ctl_find_hole(snd_card_t * card, unsigned int count) 279 { 280 unsigned int last_numid, iter = 100000; 281 282 last_numid = card->last_numid; 283 while (last_numid != snd_ctl_hole_check(card, count)) { 284 if (--iter == 0) { 285 /* this situation is very unlikely */ 286 snd_printk(KERN_ERR "unable to allocate new control numid\n"); 287 return -ENOMEM; 288 } 289 last_numid = card->last_numid; 290 } 291 return 0; 292 } 293 294 /** 295 * snd_ctl_add - add the control instance to the card 296 * @card: the card instance 297 * @kcontrol: the control instance to add 298 * 299 * Adds the control instance created via snd_ctl_new() or 300 * snd_ctl_new1() to the given card. Assigns also an unique 301 * numid used for fast search. 302 * 303 * Returns zero if successful, or a negative error code on failure. 304 * 305 * It frees automatically the control which cannot be added. 306 */ 307 int snd_ctl_add(snd_card_t * card, snd_kcontrol_t * kcontrol) 308 { 309 snd_ctl_elem_id_t id; 310 unsigned int idx; 311 312 snd_runtime_check(card != NULL && kcontrol != NULL, return -EINVAL); 313 snd_assert(kcontrol->info != NULL, return -EINVAL); 314 id = kcontrol->id; 315 down_write(&card->controls_rwsem); 316 if (snd_ctl_find_id(card, &id)) { 317 up_write(&card->controls_rwsem); 318 snd_ctl_free_one(kcontrol); 319 snd_printd(KERN_ERR "control %i:%i:%i:%s:%i is already present\n", 320 id.iface, 321 id.device, 322 id.subdevice, 323 id.name, 324 id.index); 325 return -EBUSY; 326 } 327 if (snd_ctl_find_hole(card, kcontrol->count) < 0) { 328 up_write(&card->controls_rwsem); 329 snd_ctl_free_one(kcontrol); 330 return -ENOMEM; 331 } 332 list_add_tail(&kcontrol->list, &card->controls); 333 card->controls_count += kcontrol->count; 334 kcontrol->id.numid = card->last_numid + 1; 335 card->last_numid += kcontrol->count; 336 up_write(&card->controls_rwsem); 337 for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++) 338 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id); 339 return 0; 340 } 341 342 /** 343 * snd_ctl_remove - remove the control from the card and release it 344 * @card: the card instance 345 * @kcontrol: the control instance to remove 346 * 347 * Removes the control from the card and then releases the instance. 348 * You don't need to call snd_ctl_free_one(). You must be in 349 * the write lock - down_write(&card->controls_rwsem). 350 * 351 * Returns 0 if successful, or a negative error code on failure. 352 */ 353 int snd_ctl_remove(snd_card_t * card, snd_kcontrol_t * kcontrol) 354 { 355 snd_ctl_elem_id_t id; 356 unsigned int idx; 357 358 snd_runtime_check(card != NULL && kcontrol != NULL, return -EINVAL); 359 list_del(&kcontrol->list); 360 card->controls_count -= kcontrol->count; 361 id = kcontrol->id; 362 for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++) 363 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_REMOVE, &id); 364 snd_ctl_free_one(kcontrol); 365 return 0; 366 } 367 368 /** 369 * snd_ctl_remove_id - remove the control of the given id and release it 370 * @card: the card instance 371 * @id: the control id to remove 372 * 373 * Finds the control instance with the given id, removes it from the 374 * card list and releases it. 375 * 376 * Returns 0 if successful, or a negative error code on failure. 377 */ 378 int snd_ctl_remove_id(snd_card_t * card, snd_ctl_elem_id_t *id) 379 { 380 snd_kcontrol_t *kctl; 381 int ret; 382 383 down_write(&card->controls_rwsem); 384 kctl = snd_ctl_find_id(card, id); 385 if (kctl == NULL) { 386 up_write(&card->controls_rwsem); 387 return -ENOENT; 388 } 389 ret = snd_ctl_remove(card, kctl); 390 up_write(&card->controls_rwsem); 391 return ret; 392 } 393 394 /** 395 * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it 396 * @file: active control handle 397 * @id: the control id to remove 398 * 399 * Finds the control instance with the given id, removes it from the 400 * card list and releases it. 401 * 402 * Returns 0 if successful, or a negative error code on failure. 403 */ 404 static int snd_ctl_remove_unlocked_id(snd_ctl_file_t * file, snd_ctl_elem_id_t *id) 405 { 406 snd_card_t *card = file->card; 407 snd_kcontrol_t *kctl; 408 int idx, ret; 409 410 down_write(&card->controls_rwsem); 411 kctl = snd_ctl_find_id(card, id); 412 if (kctl == NULL) { 413 up_write(&card->controls_rwsem); 414 return -ENOENT; 415 } 416 for (idx = 0; idx < kctl->count; idx++) 417 if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) { 418 up_write(&card->controls_rwsem); 419 return -EBUSY; 420 } 421 ret = snd_ctl_remove(card, kctl); 422 up_write(&card->controls_rwsem); 423 return ret; 424 } 425 426 /** 427 * snd_ctl_rename_id - replace the id of a control on the card 428 * @card: the card instance 429 * @src_id: the old id 430 * @dst_id: the new id 431 * 432 * Finds the control with the old id from the card, and replaces the 433 * id with the new one. 434 * 435 * Returns zero if successful, or a negative error code on failure. 436 */ 437 int snd_ctl_rename_id(snd_card_t * card, snd_ctl_elem_id_t *src_id, snd_ctl_elem_id_t *dst_id) 438 { 439 snd_kcontrol_t *kctl; 440 441 down_write(&card->controls_rwsem); 442 kctl = snd_ctl_find_id(card, src_id); 443 if (kctl == NULL) { 444 up_write(&card->controls_rwsem); 445 return -ENOENT; 446 } 447 kctl->id = *dst_id; 448 kctl->id.numid = card->last_numid + 1; 449 card->last_numid += kctl->count; 450 up_write(&card->controls_rwsem); 451 return 0; 452 } 453 454 /** 455 * snd_ctl_find_numid - find the control instance with the given number-id 456 * @card: the card instance 457 * @numid: the number-id to search 458 * 459 * Finds the control instance with the given number-id from the card. 460 * 461 * Returns the pointer of the instance if found, or NULL if not. 462 * 463 * The caller must down card->controls_rwsem before calling this function 464 * (if the race condition can happen). 465 */ 466 snd_kcontrol_t *snd_ctl_find_numid(snd_card_t * card, unsigned int numid) 467 { 468 struct list_head *list; 469 snd_kcontrol_t *kctl; 470 471 snd_runtime_check(card != NULL && numid != 0, return NULL); 472 list_for_each(list, &card->controls) { 473 kctl = snd_kcontrol(list); 474 if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid) 475 return kctl; 476 } 477 return NULL; 478 } 479 480 /** 481 * snd_ctl_find_id - find the control instance with the given id 482 * @card: the card instance 483 * @id: the id to search 484 * 485 * Finds the control instance with the given id from the card. 486 * 487 * Returns the pointer of the instance if found, or NULL if not. 488 * 489 * The caller must down card->controls_rwsem before calling this function 490 * (if the race condition can happen). 491 */ 492 snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id) 493 { 494 struct list_head *list; 495 snd_kcontrol_t *kctl; 496 497 snd_runtime_check(card != NULL && id != NULL, return NULL); 498 if (id->numid != 0) 499 return snd_ctl_find_numid(card, id->numid); 500 list_for_each(list, &card->controls) { 501 kctl = snd_kcontrol(list); 502 if (kctl->id.iface != id->iface) 503 continue; 504 if (kctl->id.device != id->device) 505 continue; 506 if (kctl->id.subdevice != id->subdevice) 507 continue; 508 if (strncmp(kctl->id.name, id->name, sizeof(kctl->id.name))) 509 continue; 510 if (kctl->id.index > id->index) 511 continue; 512 if (kctl->id.index + kctl->count <= id->index) 513 continue; 514 return kctl; 515 } 516 return NULL; 517 } 518 519 static int snd_ctl_card_info(snd_card_t * card, snd_ctl_file_t * ctl, 520 unsigned int cmd, void __user *arg) 521 { 522 snd_ctl_card_info_t *info; 523 524 info = kcalloc(1, sizeof(*info), GFP_KERNEL); 525 if (! info) 526 return -ENOMEM; 527 down_read(&snd_ioctl_rwsem); 528 info->card = card->number; 529 strlcpy(info->id, card->id, sizeof(info->id)); 530 strlcpy(info->driver, card->driver, sizeof(info->driver)); 531 strlcpy(info->name, card->shortname, sizeof(info->name)); 532 strlcpy(info->longname, card->longname, sizeof(info->longname)); 533 strlcpy(info->mixername, card->mixername, sizeof(info->mixername)); 534 strlcpy(info->components, card->components, sizeof(info->components)); 535 up_read(&snd_ioctl_rwsem); 536 if (copy_to_user(arg, info, sizeof(snd_ctl_card_info_t))) { 537 kfree(info); 538 return -EFAULT; 539 } 540 kfree(info); 541 return 0; 542 } 543 544 static int snd_ctl_elem_list(snd_card_t *card, snd_ctl_elem_list_t __user *_list) 545 { 546 struct list_head *plist; 547 snd_ctl_elem_list_t list; 548 snd_kcontrol_t *kctl; 549 snd_ctl_elem_id_t *dst, *id; 550 unsigned int offset, space, first, jidx; 551 552 if (copy_from_user(&list, _list, sizeof(list))) 553 return -EFAULT; 554 offset = list.offset; 555 space = list.space; 556 first = 0; 557 /* try limit maximum space */ 558 if (space > 16384) 559 return -ENOMEM; 560 if (space > 0) { 561 /* allocate temporary buffer for atomic operation */ 562 dst = vmalloc(space * sizeof(snd_ctl_elem_id_t)); 563 if (dst == NULL) 564 return -ENOMEM; 565 down_read(&card->controls_rwsem); 566 list.count = card->controls_count; 567 plist = card->controls.next; 568 while (plist != &card->controls) { 569 if (offset == 0) 570 break; 571 kctl = snd_kcontrol(plist); 572 if (offset < kctl->count) 573 break; 574 offset -= kctl->count; 575 plist = plist->next; 576 } 577 list.used = 0; 578 id = dst; 579 while (space > 0 && plist != &card->controls) { 580 kctl = snd_kcontrol(plist); 581 for (jidx = offset; space > 0 && jidx < kctl->count; jidx++) { 582 snd_ctl_build_ioff(id, kctl, jidx); 583 id++; 584 space--; 585 list.used++; 586 } 587 plist = plist->next; 588 offset = 0; 589 } 590 up_read(&card->controls_rwsem); 591 if (list.used > 0 && copy_to_user(list.pids, dst, list.used * sizeof(snd_ctl_elem_id_t))) { 592 vfree(dst); 593 return -EFAULT; 594 } 595 vfree(dst); 596 } else { 597 down_read(&card->controls_rwsem); 598 list.count = card->controls_count; 599 up_read(&card->controls_rwsem); 600 } 601 if (copy_to_user(_list, &list, sizeof(list))) 602 return -EFAULT; 603 return 0; 604 } 605 606 static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t *info) 607 { 608 snd_card_t *card = ctl->card; 609 snd_kcontrol_t *kctl; 610 snd_kcontrol_volatile_t *vd; 611 unsigned int index_offset; 612 int result; 613 614 down_read(&card->controls_rwsem); 615 kctl = snd_ctl_find_id(card, &info->id); 616 if (kctl == NULL) { 617 up_read(&card->controls_rwsem); 618 return -ENOENT; 619 } 620 #ifdef CONFIG_SND_DEBUG 621 info->access = 0; 622 #endif 623 result = kctl->info(kctl, info); 624 if (result >= 0) { 625 snd_assert(info->access == 0, ); 626 index_offset = snd_ctl_get_ioff(kctl, &info->id); 627 vd = &kctl->vd[index_offset]; 628 snd_ctl_build_ioff(&info->id, kctl, index_offset); 629 info->access = vd->access; 630 if (vd->owner) { 631 info->access |= SNDRV_CTL_ELEM_ACCESS_LOCK; 632 if (vd->owner == ctl) 633 info->access |= SNDRV_CTL_ELEM_ACCESS_OWNER; 634 info->owner = vd->owner_pid; 635 } else { 636 info->owner = -1; 637 } 638 } 639 up_read(&card->controls_rwsem); 640 return result; 641 } 642 643 static int snd_ctl_elem_info_user(snd_ctl_file_t *ctl, snd_ctl_elem_info_t __user *_info) 644 { 645 snd_ctl_elem_info_t info; 646 int result; 647 648 if (copy_from_user(&info, _info, sizeof(info))) 649 return -EFAULT; 650 result = snd_ctl_elem_info(ctl, &info); 651 if (result >= 0) 652 if (copy_to_user(_info, &info, sizeof(info))) 653 return -EFAULT; 654 return result; 655 } 656 657 int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *control) 658 { 659 snd_kcontrol_t *kctl; 660 snd_kcontrol_volatile_t *vd; 661 unsigned int index_offset; 662 int result, indirect; 663 664 down_read(&card->controls_rwsem); 665 kctl = snd_ctl_find_id(card, &control->id); 666 if (kctl == NULL) { 667 result = -ENOENT; 668 } else { 669 index_offset = snd_ctl_get_ioff(kctl, &control->id); 670 vd = &kctl->vd[index_offset]; 671 indirect = vd->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT ? 1 : 0; 672 if (control->indirect != indirect) { 673 result = -EACCES; 674 } else { 675 if ((vd->access & SNDRV_CTL_ELEM_ACCESS_READ) && kctl->get != NULL) { 676 snd_ctl_build_ioff(&control->id, kctl, index_offset); 677 result = kctl->get(kctl, control); 678 } else { 679 result = -EPERM; 680 } 681 } 682 } 683 up_read(&card->controls_rwsem); 684 return result; 685 } 686 687 static int snd_ctl_elem_read_user(snd_card_t *card, snd_ctl_elem_value_t __user *_control) 688 { 689 snd_ctl_elem_value_t *control; 690 int result; 691 692 control = kmalloc(sizeof(*control), GFP_KERNEL); 693 if (control == NULL) 694 return -ENOMEM; 695 if (copy_from_user(control, _control, sizeof(*control))) { 696 kfree(control); 697 return -EFAULT; 698 } 699 result = snd_ctl_elem_read(card, control); 700 if (result >= 0) 701 if (copy_to_user(_control, control, sizeof(*control))) 702 result = -EFAULT; 703 kfree(control); 704 return result; 705 } 706 707 int snd_ctl_elem_write(snd_card_t *card, snd_ctl_file_t *file, snd_ctl_elem_value_t *control) 708 { 709 snd_kcontrol_t *kctl; 710 snd_kcontrol_volatile_t *vd; 711 unsigned int index_offset; 712 int result, indirect; 713 714 down_read(&card->controls_rwsem); 715 kctl = snd_ctl_find_id(card, &control->id); 716 if (kctl == NULL) { 717 result = -ENOENT; 718 } else { 719 index_offset = snd_ctl_get_ioff(kctl, &control->id); 720 vd = &kctl->vd[index_offset]; 721 indirect = vd->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT ? 1 : 0; 722 if (control->indirect != indirect) { 723 result = -EACCES; 724 } else { 725 if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || 726 kctl->put == NULL || 727 (file && vd->owner != NULL && vd->owner != file)) { 728 result = -EPERM; 729 } else { 730 snd_ctl_build_ioff(&control->id, kctl, index_offset); 731 result = kctl->put(kctl, control); 732 } 733 if (result > 0) { 734 up_read(&card->controls_rwsem); 735 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &control->id); 736 return 0; 737 } 738 } 739 } 740 up_read(&card->controls_rwsem); 741 return result; 742 } 743 744 static int snd_ctl_elem_write_user(snd_ctl_file_t *file, snd_ctl_elem_value_t __user *_control) 745 { 746 snd_ctl_elem_value_t *control; 747 int result; 748 749 control = kmalloc(sizeof(*control), GFP_KERNEL); 750 if (control == NULL) 751 return -ENOMEM; 752 if (copy_from_user(control, _control, sizeof(*control))) { 753 kfree(control); 754 return -EFAULT; 755 } 756 result = snd_ctl_elem_write(file->card, file, control); 757 if (result >= 0) 758 if (copy_to_user(_control, control, sizeof(*control))) 759 result = -EFAULT; 760 kfree(control); 761 return result; 762 } 763 764 static int snd_ctl_elem_lock(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_id) 765 { 766 snd_card_t *card = file->card; 767 snd_ctl_elem_id_t id; 768 snd_kcontrol_t *kctl; 769 snd_kcontrol_volatile_t *vd; 770 int result; 771 772 if (copy_from_user(&id, _id, sizeof(id))) 773 return -EFAULT; 774 down_write(&card->controls_rwsem); 775 kctl = snd_ctl_find_id(card, &id); 776 if (kctl == NULL) { 777 result = -ENOENT; 778 } else { 779 vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)]; 780 if (vd->owner != NULL) 781 result = -EBUSY; 782 else { 783 vd->owner = file; 784 vd->owner_pid = current->pid; 785 result = 0; 786 } 787 } 788 up_write(&card->controls_rwsem); 789 return result; 790 } 791 792 static int snd_ctl_elem_unlock(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_id) 793 { 794 snd_card_t *card = file->card; 795 snd_ctl_elem_id_t id; 796 snd_kcontrol_t *kctl; 797 snd_kcontrol_volatile_t *vd; 798 int result; 799 800 if (copy_from_user(&id, _id, sizeof(id))) 801 return -EFAULT; 802 down_write(&card->controls_rwsem); 803 kctl = snd_ctl_find_id(card, &id); 804 if (kctl == NULL) { 805 result = -ENOENT; 806 } else { 807 vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)]; 808 if (vd->owner == NULL) 809 result = -EINVAL; 810 else if (vd->owner != file) 811 result = -EPERM; 812 else { 813 vd->owner = NULL; 814 vd->owner_pid = 0; 815 result = 0; 816 } 817 } 818 up_write(&card->controls_rwsem); 819 return result; 820 } 821 822 struct user_element { 823 snd_ctl_elem_info_t info; 824 void *elem_data; /* element data */ 825 unsigned long elem_data_size; /* size of element data in bytes */ 826 void *priv_data; /* private data (like strings for enumerated type) */ 827 unsigned long priv_data_size; /* size of private data in bytes */ 828 }; 829 830 static int snd_ctl_elem_user_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 831 { 832 struct user_element *ue = kcontrol->private_data; 833 834 *uinfo = ue->info; 835 return 0; 836 } 837 838 static int snd_ctl_elem_user_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 839 { 840 struct user_element *ue = kcontrol->private_data; 841 842 memcpy(&ucontrol->value, ue->elem_data, ue->elem_data_size); 843 return 0; 844 } 845 846 static int snd_ctl_elem_user_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 847 { 848 int change; 849 struct user_element *ue = kcontrol->private_data; 850 851 change = memcmp(&ucontrol->value, ue->elem_data, ue->elem_data_size) != 0; 852 if (change) 853 memcpy(ue->elem_data, &ucontrol->value, ue->elem_data_size); 854 return change; 855 } 856 857 static void snd_ctl_elem_user_free(snd_kcontrol_t * kcontrol) 858 { 859 kfree(kcontrol->private_data); 860 } 861 862 static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t *info, int replace) 863 { 864 snd_card_t *card = file->card; 865 snd_kcontrol_t kctl, *_kctl; 866 unsigned int access; 867 long private_size; 868 struct user_element *ue; 869 int idx, err; 870 871 if (card->user_ctl_count >= MAX_USER_CONTROLS) 872 return -ENOMEM; 873 if (info->count > 1024) 874 return -EINVAL; 875 access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : 876 (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|SNDRV_CTL_ELEM_ACCESS_INACTIVE)); 877 info->id.numid = 0; 878 memset(&kctl, 0, sizeof(kctl)); 879 down_write(&card->controls_rwsem); 880 _kctl = snd_ctl_find_id(card, &info->id); 881 err = 0; 882 if (_kctl) { 883 if (replace) 884 err = snd_ctl_remove(card, _kctl); 885 else 886 err = -EBUSY; 887 } else { 888 if (replace) 889 err = -ENOENT; 890 } 891 up_write(&card->controls_rwsem); 892 if (err < 0) 893 return err; 894 memcpy(&kctl.id, &info->id, sizeof(info->id)); 895 kctl.count = info->owner ? info->owner : 1; 896 access |= SNDRV_CTL_ELEM_ACCESS_USER; 897 kctl.info = snd_ctl_elem_user_info; 898 if (access & SNDRV_CTL_ELEM_ACCESS_READ) 899 kctl.get = snd_ctl_elem_user_get; 900 if (access & SNDRV_CTL_ELEM_ACCESS_WRITE) 901 kctl.put = snd_ctl_elem_user_put; 902 switch (info->type) { 903 case SNDRV_CTL_ELEM_TYPE_BOOLEAN: 904 private_size = sizeof(char); 905 if (info->count > 128) 906 return -EINVAL; 907 break; 908 case SNDRV_CTL_ELEM_TYPE_INTEGER: 909 private_size = sizeof(long); 910 if (info->count > 128) 911 return -EINVAL; 912 break; 913 case SNDRV_CTL_ELEM_TYPE_INTEGER64: 914 private_size = sizeof(long long); 915 if (info->count > 64) 916 return -EINVAL; 917 break; 918 case SNDRV_CTL_ELEM_TYPE_BYTES: 919 private_size = sizeof(unsigned char); 920 if (info->count > 512) 921 return -EINVAL; 922 break; 923 case SNDRV_CTL_ELEM_TYPE_IEC958: 924 private_size = sizeof(struct sndrv_aes_iec958); 925 if (info->count != 1) 926 return -EINVAL; 927 break; 928 default: 929 return -EINVAL; 930 } 931 private_size *= info->count; 932 ue = kcalloc(1, sizeof(struct user_element) + private_size, GFP_KERNEL); 933 if (ue == NULL) 934 return -ENOMEM; 935 ue->info = *info; 936 ue->elem_data = (char *)ue + sizeof(*ue); 937 ue->elem_data_size = private_size; 938 kctl.private_free = snd_ctl_elem_user_free; 939 _kctl = snd_ctl_new(&kctl, access); 940 if (_kctl == NULL) { 941 kfree(_kctl->private_data); 942 return -ENOMEM; 943 } 944 _kctl->private_data = ue; 945 for (idx = 0; idx < _kctl->count; idx++) 946 _kctl->vd[idx].owner = file; 947 err = snd_ctl_add(card, _kctl); 948 if (err < 0) { 949 snd_ctl_free_one(_kctl); 950 return err; 951 } 952 953 down_write(&card->controls_rwsem); 954 card->user_ctl_count++; 955 up_write(&card->controls_rwsem); 956 957 return 0; 958 } 959 960 static int snd_ctl_elem_add_user(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_info, int replace) 961 { 962 snd_ctl_elem_info_t info; 963 if (copy_from_user(&info, _info, sizeof(info))) 964 return -EFAULT; 965 return snd_ctl_elem_add(file, &info, replace); 966 } 967 968 static int snd_ctl_elem_remove(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_id) 969 { 970 snd_ctl_elem_id_t id; 971 int err; 972 973 if (copy_from_user(&id, _id, sizeof(id))) 974 return -EFAULT; 975 err = snd_ctl_remove_unlocked_id(file, &id); 976 if (! err) { 977 snd_card_t *card = file->card; 978 down_write(&card->controls_rwsem); 979 card->user_ctl_count--; 980 up_write(&card->controls_rwsem); 981 } 982 return err; 983 } 984 985 static int snd_ctl_subscribe_events(snd_ctl_file_t *file, int __user *ptr) 986 { 987 int subscribe; 988 if (get_user(subscribe, ptr)) 989 return -EFAULT; 990 if (subscribe < 0) { 991 subscribe = file->subscribed; 992 if (put_user(subscribe, ptr)) 993 return -EFAULT; 994 return 0; 995 } 996 if (subscribe) { 997 file->subscribed = 1; 998 return 0; 999 } else if (file->subscribed) { 1000 snd_ctl_empty_read_queue(file); 1001 file->subscribed = 0; 1002 } 1003 return 0; 1004 } 1005 1006 #ifdef CONFIG_PM 1007 /* 1008 * change the power state 1009 */ 1010 static int snd_ctl_set_power_state(snd_card_t *card, unsigned int power_state) 1011 { 1012 switch (power_state) { 1013 case SNDRV_CTL_POWER_D0: 1014 if (card->power_state != power_state) { 1015 card->pm_resume(card); 1016 snd_power_change_state(card, power_state); 1017 } 1018 break; 1019 case SNDRV_CTL_POWER_D3hot: 1020 if (card->power_state != power_state) { 1021 card->pm_suspend(card, PMSG_SUSPEND); 1022 snd_power_change_state(card, power_state); 1023 } 1024 break; 1025 case SNDRV_CTL_POWER_D1: 1026 case SNDRV_CTL_POWER_D2: 1027 case SNDRV_CTL_POWER_D3cold: 1028 /* not supported yet */ 1029 default: 1030 return -EINVAL; 1031 } 1032 return 0; 1033 } 1034 #endif 1035 1036 static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 1037 { 1038 snd_ctl_file_t *ctl; 1039 snd_card_t *card; 1040 struct list_head *list; 1041 snd_kctl_ioctl_t *p; 1042 void __user *argp = (void __user *)arg; 1043 int __user *ip = argp; 1044 int err; 1045 1046 ctl = file->private_data; 1047 card = ctl->card; 1048 snd_assert(card != NULL, return -ENXIO); 1049 switch (cmd) { 1050 case SNDRV_CTL_IOCTL_PVERSION: 1051 return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0; 1052 case SNDRV_CTL_IOCTL_CARD_INFO: 1053 return snd_ctl_card_info(card, ctl, cmd, argp); 1054 case SNDRV_CTL_IOCTL_ELEM_LIST: 1055 return snd_ctl_elem_list(ctl->card, argp); 1056 case SNDRV_CTL_IOCTL_ELEM_INFO: 1057 return snd_ctl_elem_info_user(ctl, argp); 1058 case SNDRV_CTL_IOCTL_ELEM_READ: 1059 return snd_ctl_elem_read_user(ctl->card, argp); 1060 case SNDRV_CTL_IOCTL_ELEM_WRITE: 1061 return snd_ctl_elem_write_user(ctl, argp); 1062 case SNDRV_CTL_IOCTL_ELEM_LOCK: 1063 return snd_ctl_elem_lock(ctl, argp); 1064 case SNDRV_CTL_IOCTL_ELEM_UNLOCK: 1065 return snd_ctl_elem_unlock(ctl, argp); 1066 case SNDRV_CTL_IOCTL_ELEM_ADD: 1067 return snd_ctl_elem_add_user(ctl, argp, 0); 1068 case SNDRV_CTL_IOCTL_ELEM_REPLACE: 1069 return snd_ctl_elem_add_user(ctl, argp, 1); 1070 case SNDRV_CTL_IOCTL_ELEM_REMOVE: 1071 return snd_ctl_elem_remove(ctl, argp); 1072 case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: 1073 return snd_ctl_subscribe_events(ctl, ip); 1074 case SNDRV_CTL_IOCTL_POWER: 1075 if (get_user(err, ip)) 1076 return -EFAULT; 1077 if (!capable(CAP_SYS_ADMIN)) 1078 return -EPERM; 1079 #ifdef CONFIG_PM 1080 if (card->pm_suspend && card->pm_resume) { 1081 snd_power_lock(card); 1082 err = snd_ctl_set_power_state(card, err); 1083 snd_power_unlock(card); 1084 } else 1085 #endif 1086 err = -ENOPROTOOPT; 1087 return err; 1088 case SNDRV_CTL_IOCTL_POWER_STATE: 1089 #ifdef CONFIG_PM 1090 return put_user(card->power_state, ip) ? -EFAULT : 0; 1091 #else 1092 return put_user(SNDRV_CTL_POWER_D0, ip) ? -EFAULT : 0; 1093 #endif 1094 } 1095 down_read(&snd_ioctl_rwsem); 1096 list_for_each(list, &snd_control_ioctls) { 1097 p = list_entry(list, snd_kctl_ioctl_t, list); 1098 err = p->fioctl(card, ctl, cmd, arg); 1099 if (err != -ENOIOCTLCMD) { 1100 up_read(&snd_ioctl_rwsem); 1101 return err; 1102 } 1103 } 1104 up_read(&snd_ioctl_rwsem); 1105 snd_printd("unknown ioctl = 0x%x\n", cmd); 1106 return -ENOTTY; 1107 } 1108 1109 static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count, loff_t * offset) 1110 { 1111 snd_ctl_file_t *ctl; 1112 int err = 0; 1113 ssize_t result = 0; 1114 1115 ctl = file->private_data; 1116 snd_assert(ctl != NULL && ctl->card != NULL, return -ENXIO); 1117 if (!ctl->subscribed) 1118 return -EBADFD; 1119 if (count < sizeof(snd_ctl_event_t)) 1120 return -EINVAL; 1121 spin_lock_irq(&ctl->read_lock); 1122 while (count >= sizeof(snd_ctl_event_t)) { 1123 snd_ctl_event_t ev; 1124 snd_kctl_event_t *kev; 1125 while (list_empty(&ctl->events)) { 1126 wait_queue_t wait; 1127 if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) { 1128 err = -EAGAIN; 1129 goto __end_lock; 1130 } 1131 init_waitqueue_entry(&wait, current); 1132 add_wait_queue(&ctl->change_sleep, &wait); 1133 set_current_state(TASK_INTERRUPTIBLE); 1134 spin_unlock_irq(&ctl->read_lock); 1135 schedule(); 1136 remove_wait_queue(&ctl->change_sleep, &wait); 1137 if (signal_pending(current)) 1138 return result > 0 ? result : -ERESTARTSYS; 1139 spin_lock_irq(&ctl->read_lock); 1140 } 1141 kev = snd_kctl_event(ctl->events.next); 1142 ev.type = SNDRV_CTL_EVENT_ELEM; 1143 ev.data.elem.mask = kev->mask; 1144 ev.data.elem.id = kev->id; 1145 list_del(&kev->list); 1146 spin_unlock_irq(&ctl->read_lock); 1147 kfree(kev); 1148 if (copy_to_user(buffer, &ev, sizeof(snd_ctl_event_t))) { 1149 err = -EFAULT; 1150 goto __end; 1151 } 1152 spin_lock_irq(&ctl->read_lock); 1153 buffer += sizeof(snd_ctl_event_t); 1154 count -= sizeof(snd_ctl_event_t); 1155 result += sizeof(snd_ctl_event_t); 1156 } 1157 __end_lock: 1158 spin_unlock_irq(&ctl->read_lock); 1159 __end: 1160 return result > 0 ? result : err; 1161 } 1162 1163 static unsigned int snd_ctl_poll(struct file *file, poll_table * wait) 1164 { 1165 unsigned int mask; 1166 snd_ctl_file_t *ctl; 1167 1168 ctl = file->private_data; 1169 if (!ctl->subscribed) 1170 return 0; 1171 poll_wait(file, &ctl->change_sleep, wait); 1172 1173 mask = 0; 1174 if (!list_empty(&ctl->events)) 1175 mask |= POLLIN | POLLRDNORM; 1176 1177 return mask; 1178 } 1179 1180 /* 1181 * register the device-specific control-ioctls. 1182 * called from each device manager like pcm.c, hwdep.c, etc. 1183 */ 1184 static int _snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists) 1185 { 1186 snd_kctl_ioctl_t *pn; 1187 1188 pn = kcalloc(1, sizeof(snd_kctl_ioctl_t), GFP_KERNEL); 1189 if (pn == NULL) 1190 return -ENOMEM; 1191 pn->fioctl = fcn; 1192 down_write(&snd_ioctl_rwsem); 1193 list_add_tail(&pn->list, lists); 1194 up_write(&snd_ioctl_rwsem); 1195 return 0; 1196 } 1197 1198 int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn) 1199 { 1200 return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls); 1201 } 1202 1203 #ifdef CONFIG_COMPAT 1204 int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn) 1205 { 1206 return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls); 1207 } 1208 #endif 1209 1210 /* 1211 * de-register the device-specific control-ioctls. 1212 */ 1213 static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists) 1214 { 1215 struct list_head *list; 1216 snd_kctl_ioctl_t *p; 1217 1218 snd_runtime_check(fcn != NULL, return -EINVAL); 1219 down_write(&snd_ioctl_rwsem); 1220 list_for_each(list, lists) { 1221 p = list_entry(list, snd_kctl_ioctl_t, list); 1222 if (p->fioctl == fcn) { 1223 list_del(&p->list); 1224 up_write(&snd_ioctl_rwsem); 1225 kfree(p); 1226 return 0; 1227 } 1228 } 1229 up_write(&snd_ioctl_rwsem); 1230 snd_BUG(); 1231 return -EINVAL; 1232 } 1233 1234 int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn) 1235 { 1236 return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls); 1237 } 1238 1239 #ifdef CONFIG_COMPAT 1240 int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn) 1241 { 1242 return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls); 1243 } 1244 1245 #endif 1246 1247 static int snd_ctl_fasync(int fd, struct file * file, int on) 1248 { 1249 snd_ctl_file_t *ctl; 1250 int err; 1251 ctl = file->private_data; 1252 err = fasync_helper(fd, file, on, &ctl->fasync); 1253 if (err < 0) 1254 return err; 1255 return 0; 1256 } 1257 1258 /* 1259 * ioctl32 compat 1260 */ 1261 #ifdef CONFIG_COMPAT 1262 #include "control_compat.c" 1263 #else 1264 #define snd_ctl_ioctl_compat NULL 1265 #endif 1266 1267 /* 1268 * INIT PART 1269 */ 1270 1271 static struct file_operations snd_ctl_f_ops = 1272 { 1273 .owner = THIS_MODULE, 1274 .read = snd_ctl_read, 1275 .open = snd_ctl_open, 1276 .release = snd_ctl_release, 1277 .poll = snd_ctl_poll, 1278 .unlocked_ioctl = snd_ctl_ioctl, 1279 .compat_ioctl = snd_ctl_ioctl_compat, 1280 .fasync = snd_ctl_fasync, 1281 }; 1282 1283 static snd_minor_t snd_ctl_reg = 1284 { 1285 .comment = "ctl", 1286 .f_ops = &snd_ctl_f_ops, 1287 }; 1288 1289 /* 1290 * registration of the control device 1291 */ 1292 static int snd_ctl_dev_register(snd_device_t *device) 1293 { 1294 snd_card_t *card = device->device_data; 1295 int err, cardnum; 1296 char name[16]; 1297 1298 snd_assert(card != NULL, return -ENXIO); 1299 cardnum = card->number; 1300 snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); 1301 sprintf(name, "controlC%i", cardnum); 1302 if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, 1303 card, 0, &snd_ctl_reg, name)) < 0) 1304 return err; 1305 return 0; 1306 } 1307 1308 /* 1309 * disconnection of the control device 1310 */ 1311 static int snd_ctl_dev_disconnect(snd_device_t *device) 1312 { 1313 snd_card_t *card = device->device_data; 1314 struct list_head *flist; 1315 snd_ctl_file_t *ctl; 1316 1317 down_read(&card->controls_rwsem); 1318 list_for_each(flist, &card->ctl_files) { 1319 ctl = snd_ctl_file(flist); 1320 wake_up(&ctl->change_sleep); 1321 kill_fasync(&ctl->fasync, SIGIO, POLL_ERR); 1322 } 1323 up_read(&card->controls_rwsem); 1324 return 0; 1325 } 1326 1327 /* 1328 * free all controls 1329 */ 1330 static int snd_ctl_dev_free(snd_device_t *device) 1331 { 1332 snd_card_t *card = device->device_data; 1333 snd_kcontrol_t *control; 1334 1335 down_write(&card->controls_rwsem); 1336 while (!list_empty(&card->controls)) { 1337 control = snd_kcontrol(card->controls.next); 1338 snd_ctl_remove(card, control); 1339 } 1340 up_write(&card->controls_rwsem); 1341 return 0; 1342 } 1343 1344 /* 1345 * de-registration of the control device 1346 */ 1347 static int snd_ctl_dev_unregister(snd_device_t *device) 1348 { 1349 snd_card_t *card = device->device_data; 1350 int err, cardnum; 1351 1352 snd_assert(card != NULL, return -ENXIO); 1353 cardnum = card->number; 1354 snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); 1355 if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL, card, 0)) < 0) 1356 return err; 1357 return snd_ctl_dev_free(device); 1358 } 1359 1360 /* 1361 * create control core: 1362 * called from init.c 1363 */ 1364 int snd_ctl_create(snd_card_t *card) 1365 { 1366 static snd_device_ops_t ops = { 1367 .dev_free = snd_ctl_dev_free, 1368 .dev_register = snd_ctl_dev_register, 1369 .dev_disconnect = snd_ctl_dev_disconnect, 1370 .dev_unregister = snd_ctl_dev_unregister 1371 }; 1372 1373 snd_assert(card != NULL, return -ENXIO); 1374 return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); 1375 } 1376