diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/timer.c | 279 |
1 files changed, 167 insertions, 112 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c index 488c28ac56c0..1b90a38d10ff 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -55,7 +55,7 @@ MODULE_PARM_DESC(timer_limit, "Maximum global timers in system."); | |||
55 | 55 | ||
56 | typedef struct { | 56 | typedef struct { |
57 | snd_timer_instance_t *timeri; | 57 | snd_timer_instance_t *timeri; |
58 | int tread; /* enhanced read with timestamps and events */ | 58 | int tread; /* enhanced read with timestamps and events */ |
59 | unsigned long ticks; | 59 | unsigned long ticks; |
60 | unsigned long overrun; | 60 | unsigned long overrun; |
61 | int qhead; | 61 | int qhead; |
@@ -95,7 +95,8 @@ static void snd_timer_reschedule(snd_timer_t * timer, unsigned long ticks_left); | |||
95 | * create a timer instance with the given owner string. | 95 | * create a timer instance with the given owner string. |
96 | * when timer is not NULL, increments the module counter | 96 | * when timer is not NULL, increments the module counter |
97 | */ | 97 | */ |
98 | static snd_timer_instance_t *snd_timer_instance_new(char *owner, snd_timer_t *timer) | 98 | static snd_timer_instance_t *snd_timer_instance_new(char *owner, |
99 | snd_timer_t *timer) | ||
99 | { | 100 | { |
100 | snd_timer_instance_t *timeri; | 101 | snd_timer_instance_t *timeri; |
101 | timeri = kzalloc(sizeof(*timeri), GFP_KERNEL); | 102 | timeri = kzalloc(sizeof(*timeri), GFP_KERNEL); |
@@ -192,7 +193,8 @@ static void snd_timer_check_slave(snd_timer_instance_t *slave) | |||
192 | if (slave->slave_class == master->slave_class && | 193 | if (slave->slave_class == master->slave_class && |
193 | slave->slave_id == master->slave_id) { | 194 | slave->slave_id == master->slave_id) { |
194 | list_del(&slave->open_list); | 195 | list_del(&slave->open_list); |
195 | list_add_tail(&slave->open_list, &master->slave_list_head); | 196 | list_add_tail(&slave->open_list, |
197 | &master->slave_list_head); | ||
196 | spin_lock_irq(&slave_active_lock); | 198 | spin_lock_irq(&slave_active_lock); |
197 | slave->master = master; | 199 | slave->master = master; |
198 | slave->timer = master->timer; | 200 | slave->timer = master->timer; |
@@ -225,7 +227,8 @@ static void snd_timer_check_master(snd_timer_instance_t *master) | |||
225 | slave->master = master; | 227 | slave->master = master; |
226 | slave->timer = master->timer; | 228 | slave->timer = master->timer; |
227 | if (slave->flags & SNDRV_TIMER_IFLG_RUNNING) | 229 | if (slave->flags & SNDRV_TIMER_IFLG_RUNNING) |
228 | list_add_tail(&slave->active_list, &master->slave_active_head); | 230 | list_add_tail(&slave->active_list, |
231 | &master->slave_active_head); | ||
229 | spin_unlock_irq(&slave_active_lock); | 232 | spin_unlock_irq(&slave_active_lock); |
230 | } | 233 | } |
231 | } | 234 | } |
@@ -241,7 +244,7 @@ int snd_timer_open(snd_timer_instance_t **ti, | |||
241 | { | 244 | { |
242 | snd_timer_t *timer; | 245 | snd_timer_t *timer; |
243 | snd_timer_instance_t *timeri = NULL; | 246 | snd_timer_instance_t *timeri = NULL; |
244 | 247 | ||
245 | if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) { | 248 | if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) { |
246 | /* open a slave instance */ | 249 | /* open a slave instance */ |
247 | if (tid->dev_sclass <= SNDRV_TIMER_SCLASS_NONE || | 250 | if (tid->dev_sclass <= SNDRV_TIMER_SCLASS_NONE || |
@@ -304,7 +307,8 @@ int snd_timer_open(snd_timer_instance_t **ti, | |||
304 | return 0; | 307 | return 0; |
305 | } | 308 | } |
306 | 309 | ||
307 | static int _snd_timer_stop(snd_timer_instance_t * timeri, int keep_flag, enum sndrv_timer_event event); | 310 | static int _snd_timer_stop(snd_timer_instance_t * timeri, |
311 | int keep_flag, enum sndrv_timer_event event); | ||
308 | 312 | ||
309 | /* | 313 | /* |
310 | * close a timer instance | 314 | * close a timer instance |
@@ -344,7 +348,8 @@ int snd_timer_close(snd_timer_instance_t * timeri) | |||
344 | spin_unlock_irq(&timer->lock); | 348 | spin_unlock_irq(&timer->lock); |
345 | down(®ister_mutex); | 349 | down(®ister_mutex); |
346 | list_del(&timeri->open_list); | 350 | list_del(&timeri->open_list); |
347 | if (timer && list_empty(&timer->open_list_head) && timer->hw.close) | 351 | if (timer && list_empty(&timer->open_list_head) && |
352 | timer->hw.close) | ||
348 | timer->hw.close(timer); | 353 | timer->hw.close(timer); |
349 | /* remove slave links */ | 354 | /* remove slave links */ |
350 | list_for_each_safe(p, n, &timeri->slave_list_head) { | 355 | list_for_each_safe(p, n, &timeri->slave_list_head) { |
@@ -382,7 +387,8 @@ unsigned long snd_timer_resolution(snd_timer_instance_t * timeri) | |||
382 | return 0; | 387 | return 0; |
383 | } | 388 | } |
384 | 389 | ||
385 | static void snd_timer_notify1(snd_timer_instance_t *ti, enum sndrv_timer_event event) | 390 | static void snd_timer_notify1(snd_timer_instance_t *ti, |
391 | enum sndrv_timer_event event) | ||
386 | { | 392 | { |
387 | snd_timer_t *timer; | 393 | snd_timer_t *timer; |
388 | unsigned long flags; | 394 | unsigned long flags; |
@@ -392,8 +398,10 @@ static void snd_timer_notify1(snd_timer_instance_t *ti, enum sndrv_timer_event e | |||
392 | struct timespec tstamp; | 398 | struct timespec tstamp; |
393 | 399 | ||
394 | getnstimeofday(&tstamp); | 400 | getnstimeofday(&tstamp); |
395 | snd_assert(event >= SNDRV_TIMER_EVENT_START && event <= SNDRV_TIMER_EVENT_PAUSE, return); | 401 | snd_assert(event >= SNDRV_TIMER_EVENT_START && |
396 | if (event == SNDRV_TIMER_EVENT_START || event == SNDRV_TIMER_EVENT_CONTINUE) | 402 | event <= SNDRV_TIMER_EVENT_PAUSE, return); |
403 | if (event == SNDRV_TIMER_EVENT_START || | ||
404 | event == SNDRV_TIMER_EVENT_CONTINUE) | ||
397 | resolution = snd_timer_resolution(ti); | 405 | resolution = snd_timer_resolution(ti); |
398 | if (ti->ccallback) | 406 | if (ti->ccallback) |
399 | ti->ccallback(ti, SNDRV_TIMER_EVENT_START, &tstamp, resolution); | 407 | ti->ccallback(ti, SNDRV_TIMER_EVENT_START, &tstamp, resolution); |
@@ -413,7 +421,8 @@ static void snd_timer_notify1(snd_timer_instance_t *ti, enum sndrv_timer_event e | |||
413 | spin_unlock_irqrestore(&timer->lock, flags); | 421 | spin_unlock_irqrestore(&timer->lock, flags); |
414 | } | 422 | } |
415 | 423 | ||
416 | static int snd_timer_start1(snd_timer_t *timer, snd_timer_instance_t *timeri, unsigned long sticks) | 424 | static int snd_timer_start1(snd_timer_t *timer, snd_timer_instance_t *timeri, |
425 | unsigned long sticks) | ||
417 | { | 426 | { |
418 | list_del(&timeri->active_list); | 427 | list_del(&timeri->active_list); |
419 | list_add_tail(&timeri->active_list, &timer->active_list_head); | 428 | list_add_tail(&timeri->active_list, &timer->active_list_head); |
@@ -440,14 +449,15 @@ static int snd_timer_start_slave(snd_timer_instance_t *timeri) | |||
440 | spin_lock_irqsave(&slave_active_lock, flags); | 449 | spin_lock_irqsave(&slave_active_lock, flags); |
441 | timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; | 450 | timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; |
442 | if (timeri->master) | 451 | if (timeri->master) |
443 | list_add_tail(&timeri->active_list, &timeri->master->slave_active_head); | 452 | list_add_tail(&timeri->active_list, |
453 | &timeri->master->slave_active_head); | ||
444 | spin_unlock_irqrestore(&slave_active_lock, flags); | 454 | spin_unlock_irqrestore(&slave_active_lock, flags); |
445 | return 1; /* delayed start */ | 455 | return 1; /* delayed start */ |
446 | } | 456 | } |
447 | 457 | ||
448 | /* | 458 | /* |
449 | * start the timer instance | 459 | * start the timer instance |
450 | */ | 460 | */ |
451 | int snd_timer_start(snd_timer_instance_t * timeri, unsigned int ticks) | 461 | int snd_timer_start(snd_timer_instance_t * timeri, unsigned int ticks) |
452 | { | 462 | { |
453 | snd_timer_t *timer; | 463 | snd_timer_t *timer; |
@@ -473,7 +483,8 @@ int snd_timer_start(snd_timer_instance_t * timeri, unsigned int ticks) | |||
473 | return result; | 483 | return result; |
474 | } | 484 | } |
475 | 485 | ||
476 | static int _snd_timer_stop(snd_timer_instance_t * timeri, int keep_flag, enum sndrv_timer_event event) | 486 | static int _snd_timer_stop(snd_timer_instance_t * timeri, |
487 | int keep_flag, enum sndrv_timer_event event) | ||
477 | { | 488 | { |
478 | snd_timer_t *timer; | 489 | snd_timer_t *timer; |
479 | unsigned long flags; | 490 | unsigned long flags; |
@@ -507,7 +518,8 @@ static int _snd_timer_stop(snd_timer_instance_t * timeri, int keep_flag, enum sn | |||
507 | } | 518 | } |
508 | } | 519 | } |
509 | if (!keep_flag) | 520 | if (!keep_flag) |
510 | timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING|SNDRV_TIMER_IFLG_START); | 521 | timeri->flags &= |
522 | ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START); | ||
511 | spin_unlock_irqrestore(&timer->lock, flags); | 523 | spin_unlock_irqrestore(&timer->lock, flags); |
512 | __end: | 524 | __end: |
513 | if (event != SNDRV_TIMER_EVENT_RESOLUTION) | 525 | if (event != SNDRV_TIMER_EVENT_RESOLUTION) |
@@ -625,7 +637,7 @@ static void snd_timer_tasklet(unsigned long arg) | |||
625 | 637 | ||
626 | /* remove from ack_list and make empty */ | 638 | /* remove from ack_list and make empty */ |
627 | list_del_init(p); | 639 | list_del_init(p); |
628 | 640 | ||
629 | ticks = ti->pticks; | 641 | ticks = ti->pticks; |
630 | ti->pticks = 0; | 642 | ti->pticks = 0; |
631 | resolution = ti->resolution; | 643 | resolution = ti->resolution; |
@@ -650,7 +662,7 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left) | |||
650 | { | 662 | { |
651 | snd_timer_instance_t *ti, *ts; | 663 | snd_timer_instance_t *ti, *ts; |
652 | unsigned long resolution, ticks; | 664 | unsigned long resolution, ticks; |
653 | struct list_head *p, *q, *n; | 665 | struct list_head *p, *q, *n, *ack_list_head; |
654 | int use_tasklet = 0; | 666 | int use_tasklet = 0; |
655 | 667 | ||
656 | if (timer == NULL) | 668 | if (timer == NULL) |
@@ -665,8 +677,9 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left) | |||
665 | resolution = timer->hw.resolution; | 677 | resolution = timer->hw.resolution; |
666 | 678 | ||
667 | /* loop for all active instances | 679 | /* loop for all active instances |
668 | * here we cannot use list_for_each because the active_list of a processed | 680 | * Here we cannot use list_for_each because the active_list of a |
669 | * instance is relinked to done_list_head before callback is called. | 681 | * processed instance is relinked to done_list_head before the callback |
682 | * is called. | ||
670 | */ | 683 | */ |
671 | list_for_each_safe(p, n, &timer->active_list_head) { | 684 | list_for_each_safe(p, n, &timer->active_list_head) { |
672 | ti = list_entry(p, snd_timer_instance_t, active_list); | 685 | ti = list_entry(p, snd_timer_instance_t, active_list); |
@@ -687,26 +700,19 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left) | |||
687 | if (--timer->running) | 700 | if (--timer->running) |
688 | list_del(p); | 701 | list_del(p); |
689 | } | 702 | } |
690 | if (list_empty(&ti->ack_list)) { | 703 | if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) || |
691 | if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) || | 704 | (ti->flags & SNDRV_TIMER_IFLG_FAST)) |
692 | (ti->flags & SNDRV_TIMER_IFLG_FAST)) { | 705 | ack_list_head = &timer->ack_list_head; |
693 | list_add_tail(&ti->ack_list, &timer->ack_list_head); | 706 | else |
694 | } else { | 707 | ack_list_head = &timer->sack_list_head; |
695 | list_add_tail(&ti->ack_list, &timer->sack_list_head); | 708 | if (list_empty(&ti->ack_list)) |
696 | } | 709 | list_add_tail(&ti->ack_list, ack_list_head); |
697 | } | ||
698 | list_for_each(q, &ti->slave_active_head) { | 710 | list_for_each(q, &ti->slave_active_head) { |
699 | ts = list_entry(q, snd_timer_instance_t, active_list); | 711 | ts = list_entry(q, snd_timer_instance_t, active_list); |
700 | ts->pticks = ti->pticks; | 712 | ts->pticks = ti->pticks; |
701 | ts->resolution = resolution; | 713 | ts->resolution = resolution; |
702 | if (list_empty(&ts->ack_list)) { | 714 | if (list_empty(&ts->ack_list)) |
703 | if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) || | 715 | list_add_tail(&ts->ack_list, ack_list_head); |
704 | (ti->flags & SNDRV_TIMER_IFLG_FAST)) { | ||
705 | list_add_tail(&ts->ack_list, &timer->ack_list_head); | ||
706 | } else { | ||
707 | list_add_tail(&ts->ack_list, &timer->sack_list_head); | ||
708 | } | ||
709 | } | ||
710 | } | 716 | } |
711 | } | 717 | } |
712 | if (timer->flags & SNDRV_TIMER_FLG_RESCHED) | 718 | if (timer->flags & SNDRV_TIMER_FLG_RESCHED) |
@@ -730,10 +736,10 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left) | |||
730 | while (!list_empty(&timer->ack_list_head)) { | 736 | while (!list_empty(&timer->ack_list_head)) { |
731 | p = timer->ack_list_head.next; /* get first item */ | 737 | p = timer->ack_list_head.next; /* get first item */ |
732 | ti = list_entry(p, snd_timer_instance_t, ack_list); | 738 | ti = list_entry(p, snd_timer_instance_t, ack_list); |
733 | 739 | ||
734 | /* remove from ack_list and make empty */ | 740 | /* remove from ack_list and make empty */ |
735 | list_del_init(p); | 741 | list_del_init(p); |
736 | 742 | ||
737 | ticks = ti->pticks; | 743 | ticks = ti->pticks; |
738 | ti->pticks = 0; | 744 | ti->pticks = 0; |
739 | 745 | ||
@@ -757,7 +763,8 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left) | |||
757 | 763 | ||
758 | */ | 764 | */ |
759 | 765 | ||
760 | int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid, snd_timer_t ** rtimer) | 766 | int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid, |
767 | snd_timer_t **rtimer) | ||
761 | { | 768 | { |
762 | snd_timer_t *timer; | 769 | snd_timer_t *timer; |
763 | int err; | 770 | int err; |
@@ -785,10 +792,12 @@ int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid, snd_timer_t * | |||
785 | INIT_LIST_HEAD(&timer->ack_list_head); | 792 | INIT_LIST_HEAD(&timer->ack_list_head); |
786 | INIT_LIST_HEAD(&timer->sack_list_head); | 793 | INIT_LIST_HEAD(&timer->sack_list_head); |
787 | spin_lock_init(&timer->lock); | 794 | spin_lock_init(&timer->lock); |
788 | tasklet_init(&timer->task_queue, snd_timer_tasklet, (unsigned long)timer); | 795 | tasklet_init(&timer->task_queue, snd_timer_tasklet, |
796 | (unsigned long)timer); | ||
789 | if (card != NULL) { | 797 | if (card != NULL) { |
790 | timer->module = card->module; | 798 | timer->module = card->module; |
791 | if ((err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops)) < 0) { | 799 | err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops); |
800 | if (err < 0) { | ||
792 | snd_timer_free(timer); | 801 | snd_timer_free(timer); |
793 | return err; | 802 | return err; |
794 | } | 803 | } |
@@ -818,7 +827,8 @@ static int snd_timer_dev_register(snd_device_t *dev) | |||
818 | snd_timer_t *timer1; | 827 | snd_timer_t *timer1; |
819 | struct list_head *p; | 828 | struct list_head *p; |
820 | 829 | ||
821 | snd_assert(timer != NULL && timer->hw.start != NULL && timer->hw.stop != NULL, return -ENXIO); | 830 | snd_assert(timer != NULL && timer->hw.start != NULL && |
831 | timer->hw.stop != NULL, return -ENXIO); | ||
822 | if (!(timer->hw.flags & SNDRV_TIMER_HW_SLAVE) && | 832 | if (!(timer->hw.flags & SNDRV_TIMER_HW_SLAVE) && |
823 | !timer->hw.resolution && timer->hw.c_resolution == NULL) | 833 | !timer->hw.resolution && timer->hw.c_resolution == NULL) |
824 | return -EINVAL; | 834 | return -EINVAL; |
@@ -879,7 +889,8 @@ static int snd_timer_dev_unregister(snd_device_t *device) | |||
879 | return snd_timer_unregister(timer); | 889 | return snd_timer_unregister(timer); |
880 | } | 890 | } |
881 | 891 | ||
882 | void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event, struct timespec *tstamp) | 892 | void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event, |
893 | struct timespec *tstamp) | ||
883 | { | 894 | { |
884 | unsigned long flags; | 895 | unsigned long flags; |
885 | unsigned long resolution = 0; | 896 | unsigned long resolution = 0; |
@@ -888,7 +899,8 @@ void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event, struct t | |||
888 | 899 | ||
889 | if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)) | 900 | if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)) |
890 | return; | 901 | return; |
891 | snd_assert(event >= SNDRV_TIMER_EVENT_MSTART && event <= SNDRV_TIMER_EVENT_MRESUME, return); | 902 | snd_assert(event >= SNDRV_TIMER_EVENT_MSTART && |
903 | event <= SNDRV_TIMER_EVENT_MRESUME, return); | ||
892 | spin_lock_irqsave(&timer->lock, flags); | 904 | spin_lock_irqsave(&timer->lock, flags); |
893 | if (event == SNDRV_TIMER_EVENT_MSTART || | 905 | if (event == SNDRV_TIMER_EVENT_MSTART || |
894 | event == SNDRV_TIMER_EVENT_MCONTINUE || | 906 | event == SNDRV_TIMER_EVENT_MCONTINUE || |
@@ -917,7 +929,7 @@ void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event, struct t | |||
917 | int snd_timer_global_new(char *id, int device, snd_timer_t **rtimer) | 929 | int snd_timer_global_new(char *id, int device, snd_timer_t **rtimer) |
918 | { | 930 | { |
919 | snd_timer_id_t tid; | 931 | snd_timer_id_t tid; |
920 | 932 | ||
921 | tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL; | 933 | tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL; |
922 | tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; | 934 | tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; |
923 | tid.card = -1; | 935 | tid.card = -1; |
@@ -945,7 +957,7 @@ int snd_timer_global_unregister(snd_timer_t *timer) | |||
945 | return snd_timer_unregister(timer); | 957 | return snd_timer_unregister(timer); |
946 | } | 958 | } |
947 | 959 | ||
948 | /* | 960 | /* |
949 | * System timer | 961 | * System timer |
950 | */ | 962 | */ |
951 | 963 | ||
@@ -1021,7 +1033,8 @@ static int snd_timer_register_system(void) | |||
1021 | struct snd_timer_system_private *priv; | 1033 | struct snd_timer_system_private *priv; |
1022 | int err; | 1034 | int err; |
1023 | 1035 | ||
1024 | if ((err = snd_timer_global_new("system", SNDRV_TIMER_GLOBAL_SYSTEM, &timer)) < 0) | 1036 | err = snd_timer_global_new("system", SNDRV_TIMER_GLOBAL_SYSTEM, &timer); |
1037 | if (err < 0) | ||
1025 | return err; | 1038 | return err; |
1026 | strcpy(timer->name, "system timer"); | 1039 | strcpy(timer->name, "system timer"); |
1027 | timer->hw = snd_timer_system; | 1040 | timer->hw = snd_timer_system; |
@@ -1058,27 +1071,35 @@ static void snd_timer_proc_read(snd_info_entry_t *entry, | |||
1058 | snd_iprintf(buffer, "G%i: ", timer->tmr_device); | 1071 | snd_iprintf(buffer, "G%i: ", timer->tmr_device); |
1059 | break; | 1072 | break; |
1060 | case SNDRV_TIMER_CLASS_CARD: | 1073 | case SNDRV_TIMER_CLASS_CARD: |
1061 | snd_iprintf(buffer, "C%i-%i: ", timer->card->number, timer->tmr_device); | 1074 | snd_iprintf(buffer, "C%i-%i: ", |
1075 | timer->card->number, timer->tmr_device); | ||
1062 | break; | 1076 | break; |
1063 | case SNDRV_TIMER_CLASS_PCM: | 1077 | case SNDRV_TIMER_CLASS_PCM: |
1064 | snd_iprintf(buffer, "P%i-%i-%i: ", timer->card->number, timer->tmr_device, timer->tmr_subdevice); | 1078 | snd_iprintf(buffer, "P%i-%i-%i: ", timer->card->number, |
1079 | timer->tmr_device, timer->tmr_subdevice); | ||
1065 | break; | 1080 | break; |
1066 | default: | 1081 | default: |
1067 | snd_iprintf(buffer, "?%i-%i-%i-%i: ", timer->tmr_class, timer->card ? timer->card->number : -1, timer->tmr_device, timer->tmr_subdevice); | 1082 | snd_iprintf(buffer, "?%i-%i-%i-%i: ", timer->tmr_class, |
1083 | timer->card ? timer->card->number : -1, | ||
1084 | timer->tmr_device, timer->tmr_subdevice); | ||
1068 | } | 1085 | } |
1069 | snd_iprintf(buffer, "%s :", timer->name); | 1086 | snd_iprintf(buffer, "%s :", timer->name); |
1070 | if (timer->hw.resolution) | 1087 | if (timer->hw.resolution) |
1071 | snd_iprintf(buffer, " %lu.%03luus (%lu ticks)", timer->hw.resolution / 1000, timer->hw.resolution % 1000, timer->hw.ticks); | 1088 | snd_iprintf(buffer, " %lu.%03luus (%lu ticks)", |
1089 | timer->hw.resolution / 1000, | ||
1090 | timer->hw.resolution % 1000, | ||
1091 | timer->hw.ticks); | ||
1072 | if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) | 1092 | if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) |
1073 | snd_iprintf(buffer, " SLAVE"); | 1093 | snd_iprintf(buffer, " SLAVE"); |
1074 | snd_iprintf(buffer, "\n"); | 1094 | snd_iprintf(buffer, "\n"); |
1075 | spin_lock_irqsave(&timer->lock, flags); | 1095 | spin_lock_irqsave(&timer->lock, flags); |
1076 | list_for_each(q, &timer->open_list_head) { | 1096 | list_for_each(q, &timer->open_list_head) { |
1077 | ti = list_entry(q, snd_timer_instance_t, open_list); | 1097 | ti = list_entry(q, snd_timer_instance_t, open_list); |
1078 | snd_iprintf(buffer, " Client %s : %s : lost interrupts %li\n", | 1098 | snd_iprintf(buffer, " Client %s : %s\n", |
1079 | ti->owner ? ti->owner : "unknown", | 1099 | ti->owner ? ti->owner : "unknown", |
1080 | ti->flags & (SNDRV_TIMER_IFLG_START|SNDRV_TIMER_IFLG_RUNNING) ? "running" : "stopped", | 1100 | ti->flags & (SNDRV_TIMER_IFLG_START | |
1081 | ti->lost); | 1101 | SNDRV_TIMER_IFLG_RUNNING) |
1102 | ? "running" : "stopped"); | ||
1082 | } | 1103 | } |
1083 | spin_unlock_irqrestore(&timer->lock, flags); | 1104 | spin_unlock_irqrestore(&timer->lock, flags); |
1084 | } | 1105 | } |
@@ -1096,7 +1117,7 @@ static void snd_timer_user_interrupt(snd_timer_instance_t *timeri, | |||
1096 | snd_timer_user_t *tu = timeri->callback_data; | 1117 | snd_timer_user_t *tu = timeri->callback_data; |
1097 | snd_timer_read_t *r; | 1118 | snd_timer_read_t *r; |
1098 | int prev; | 1119 | int prev; |
1099 | 1120 | ||
1100 | spin_lock(&tu->qlock); | 1121 | spin_lock(&tu->qlock); |
1101 | if (tu->qused > 0) { | 1122 | if (tu->qused > 0) { |
1102 | prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1; | 1123 | prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1; |
@@ -1121,7 +1142,8 @@ static void snd_timer_user_interrupt(snd_timer_instance_t *timeri, | |||
1121 | wake_up(&tu->qchange_sleep); | 1142 | wake_up(&tu->qchange_sleep); |
1122 | } | 1143 | } |
1123 | 1144 | ||
1124 | static void snd_timer_user_append_to_tqueue(snd_timer_user_t *tu, snd_timer_tread_t *tread) | 1145 | static void snd_timer_user_append_to_tqueue(snd_timer_user_t *tu, |
1146 | snd_timer_tread_t *tread) | ||
1125 | { | 1147 | { |
1126 | if (tu->qused >= tu->queue_size) { | 1148 | if (tu->qused >= tu->queue_size) { |
1127 | tu->overrun++; | 1149 | tu->overrun++; |
@@ -1140,7 +1162,8 @@ static void snd_timer_user_ccallback(snd_timer_instance_t *timeri, | |||
1140 | snd_timer_user_t *tu = timeri->callback_data; | 1162 | snd_timer_user_t *tu = timeri->callback_data; |
1141 | snd_timer_tread_t r1; | 1163 | snd_timer_tread_t r1; |
1142 | 1164 | ||
1143 | if (event >= SNDRV_TIMER_EVENT_START && event <= SNDRV_TIMER_EVENT_PAUSE) | 1165 | if (event >= SNDRV_TIMER_EVENT_START && |
1166 | event <= SNDRV_TIMER_EVENT_PAUSE) | ||
1144 | tu->tstamp = *tstamp; | 1167 | tu->tstamp = *tstamp; |
1145 | if ((tu->filter & (1 << event)) == 0 || !tu->tread) | 1168 | if ((tu->filter & (1 << event)) == 0 || !tu->tread) |
1146 | return; | 1169 | return; |
@@ -1165,13 +1188,15 @@ static void snd_timer_user_tinterrupt(snd_timer_instance_t *timeri, | |||
1165 | 1188 | ||
1166 | memset(&tstamp, 0, sizeof(tstamp)); | 1189 | memset(&tstamp, 0, sizeof(tstamp)); |
1167 | spin_lock(&tu->qlock); | 1190 | spin_lock(&tu->qlock); |
1168 | if ((tu->filter & ((1 << SNDRV_TIMER_EVENT_RESOLUTION)|(1 << SNDRV_TIMER_EVENT_TICK))) == 0) { | 1191 | if ((tu->filter & ((1 << SNDRV_TIMER_EVENT_RESOLUTION) | |
1192 | (1 << SNDRV_TIMER_EVENT_TICK))) == 0) { | ||
1169 | spin_unlock(&tu->qlock); | 1193 | spin_unlock(&tu->qlock); |
1170 | return; | 1194 | return; |
1171 | } | 1195 | } |
1172 | if (tu->last_resolution != resolution || ticks > 0) | 1196 | if (tu->last_resolution != resolution || ticks > 0) |
1173 | getnstimeofday(&tstamp); | 1197 | getnstimeofday(&tstamp); |
1174 | if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && tu->last_resolution != resolution) { | 1198 | if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && |
1199 | tu->last_resolution != resolution) { | ||
1175 | r1.event = SNDRV_TIMER_EVENT_RESOLUTION; | 1200 | r1.event = SNDRV_TIMER_EVENT_RESOLUTION; |
1176 | r1.tstamp = tstamp; | 1201 | r1.tstamp = tstamp; |
1177 | r1.val = resolution; | 1202 | r1.val = resolution; |
@@ -1209,7 +1234,7 @@ static void snd_timer_user_tinterrupt(snd_timer_instance_t *timeri, | |||
1209 | static int snd_timer_user_open(struct inode *inode, struct file *file) | 1234 | static int snd_timer_user_open(struct inode *inode, struct file *file) |
1210 | { | 1235 | { |
1211 | snd_timer_user_t *tu; | 1236 | snd_timer_user_t *tu; |
1212 | 1237 | ||
1213 | tu = kzalloc(sizeof(*tu), GFP_KERNEL); | 1238 | tu = kzalloc(sizeof(*tu), GFP_KERNEL); |
1214 | if (tu == NULL) | 1239 | if (tu == NULL) |
1215 | return -ENOMEM; | 1240 | return -ENOMEM; |
@@ -1218,7 +1243,8 @@ static int snd_timer_user_open(struct inode *inode, struct file *file) | |||
1218 | init_MUTEX(&tu->tread_sem); | 1243 | init_MUTEX(&tu->tread_sem); |
1219 | tu->ticks = 1; | 1244 | tu->ticks = 1; |
1220 | tu->queue_size = 128; | 1245 | tu->queue_size = 128; |
1221 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); | 1246 | tu->queue = kmalloc(tu->queue_size * sizeof(snd_timer_read_t), |
1247 | GFP_KERNEL); | ||
1222 | if (tu->queue == NULL) { | 1248 | if (tu->queue == NULL) { |
1223 | kfree(tu); | 1249 | kfree(tu); |
1224 | return -ENOMEM; | 1250 | return -ENOMEM; |
@@ -1267,7 +1293,7 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid) | |||
1267 | snd_timer_id_t id; | 1293 | snd_timer_id_t id; |
1268 | snd_timer_t *timer; | 1294 | snd_timer_t *timer; |
1269 | struct list_head *p; | 1295 | struct list_head *p; |
1270 | 1296 | ||
1271 | if (copy_from_user(&id, _tid, sizeof(id))) | 1297 | if (copy_from_user(&id, _tid, sizeof(id))) |
1272 | return -EFAULT; | 1298 | return -EFAULT; |
1273 | down(®ister_mutex); | 1299 | down(®ister_mutex); |
@@ -1308,7 +1334,11 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid) | |||
1308 | if (id.device < 0) { | 1334 | if (id.device < 0) { |
1309 | id.device = 0; | 1335 | id.device = 0; |
1310 | } else { | 1336 | } else { |
1311 | id.subdevice = id.subdevice < 0 ? 0 : id.subdevice + 1; | 1337 | if (id.subdevice < 0) { |
1338 | id.subdevice = 0; | ||
1339 | } else { | ||
1340 | id.subdevice++; | ||
1341 | } | ||
1312 | } | 1342 | } |
1313 | } | 1343 | } |
1314 | } | 1344 | } |
@@ -1352,9 +1382,10 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid) | |||
1352 | if (copy_to_user(_tid, &id, sizeof(*_tid))) | 1382 | if (copy_to_user(_tid, &id, sizeof(*_tid))) |
1353 | return -EFAULT; | 1383 | return -EFAULT; |
1354 | return 0; | 1384 | return 0; |
1355 | } | 1385 | } |
1356 | 1386 | ||
1357 | static int snd_timer_user_ginfo(struct file *file, snd_timer_ginfo_t __user *_ginfo) | 1387 | static int snd_timer_user_ginfo(struct file *file, |
1388 | snd_timer_ginfo_t __user *_ginfo) | ||
1358 | { | 1389 | { |
1359 | snd_timer_ginfo_t *ginfo; | 1390 | snd_timer_ginfo_t *ginfo; |
1360 | snd_timer_id_t tid; | 1391 | snd_timer_id_t tid; |
@@ -1398,7 +1429,8 @@ static int snd_timer_user_ginfo(struct file *file, snd_timer_ginfo_t __user *_gi | |||
1398 | return err; | 1429 | return err; |
1399 | } | 1430 | } |
1400 | 1431 | ||
1401 | static int snd_timer_user_gparams(struct file *file, snd_timer_gparams_t __user *_gparams) | 1432 | static int snd_timer_user_gparams(struct file *file, |
1433 | snd_timer_gparams_t __user *_gparams) | ||
1402 | { | 1434 | { |
1403 | snd_timer_gparams_t gparams; | 1435 | snd_timer_gparams_t gparams; |
1404 | snd_timer_t *t; | 1436 | snd_timer_t *t; |
@@ -1408,23 +1440,26 @@ static int snd_timer_user_gparams(struct file *file, snd_timer_gparams_t __user | |||
1408 | return -EFAULT; | 1440 | return -EFAULT; |
1409 | down(®ister_mutex); | 1441 | down(®ister_mutex); |
1410 | t = snd_timer_find(&gparams.tid); | 1442 | t = snd_timer_find(&gparams.tid); |
1411 | if (t != NULL) { | 1443 | if (!t) { |
1412 | if (list_empty(&t->open_list_head)) { | ||
1413 | if (t->hw.set_period) | ||
1414 | err = t->hw.set_period(t, gparams.period_num, gparams.period_den); | ||
1415 | else | ||
1416 | err = -ENOSYS; | ||
1417 | } else { | ||
1418 | err = -EBUSY; | ||
1419 | } | ||
1420 | } else { | ||
1421 | err = -ENODEV; | 1444 | err = -ENODEV; |
1445 | goto _error; | ||
1446 | } | ||
1447 | if (!list_empty(&t->open_list_head)) { | ||
1448 | err = -EBUSY; | ||
1449 | goto _error; | ||
1450 | } | ||
1451 | if (!t->hw.set_period) { | ||
1452 | err = -ENOSYS; | ||
1453 | goto _error; | ||
1422 | } | 1454 | } |
1455 | err = t->hw.set_period(t, gparams.period_num, gparams.period_den); | ||
1456 | _error: | ||
1423 | up(®ister_mutex); | 1457 | up(®ister_mutex); |
1424 | return err; | 1458 | return err; |
1425 | } | 1459 | } |
1426 | 1460 | ||
1427 | static int snd_timer_user_gstatus(struct file *file, snd_timer_gstatus_t __user *_gstatus) | 1461 | static int snd_timer_user_gstatus(struct file *file, |
1462 | snd_timer_gstatus_t __user *_gstatus) | ||
1428 | { | 1463 | { |
1429 | snd_timer_gstatus_t gstatus; | 1464 | snd_timer_gstatus_t gstatus; |
1430 | snd_timer_id_t tid; | 1465 | snd_timer_id_t tid; |
@@ -1444,7 +1479,8 @@ static int snd_timer_user_gstatus(struct file *file, snd_timer_gstatus_t __user | |||
1444 | else | 1479 | else |
1445 | gstatus.resolution = t->hw.resolution; | 1480 | gstatus.resolution = t->hw.resolution; |
1446 | if (t->hw.precise_resolution) { | 1481 | if (t->hw.precise_resolution) { |
1447 | t->hw.precise_resolution(t, &gstatus.resolution_num, &gstatus.resolution_den); | 1482 | t->hw.precise_resolution(t, &gstatus.resolution_num, |
1483 | &gstatus.resolution_den); | ||
1448 | } else { | 1484 | } else { |
1449 | gstatus.resolution_num = gstatus.resolution; | 1485 | gstatus.resolution_num = gstatus.resolution; |
1450 | gstatus.resolution_den = 1000000000uL; | 1486 | gstatus.resolution_den = 1000000000uL; |
@@ -1458,13 +1494,14 @@ static int snd_timer_user_gstatus(struct file *file, snd_timer_gstatus_t __user | |||
1458 | return err; | 1494 | return err; |
1459 | } | 1495 | } |
1460 | 1496 | ||
1461 | static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user *_tselect) | 1497 | static int snd_timer_user_tselect(struct file *file, |
1498 | snd_timer_select_t __user *_tselect) | ||
1462 | { | 1499 | { |
1463 | snd_timer_user_t *tu; | 1500 | snd_timer_user_t *tu; |
1464 | snd_timer_select_t tselect; | 1501 | snd_timer_select_t tselect; |
1465 | char str[32]; | 1502 | char str[32]; |
1466 | int err = 0; | 1503 | int err = 0; |
1467 | 1504 | ||
1468 | tu = file->private_data; | 1505 | tu = file->private_data; |
1469 | down(&tu->tread_sem); | 1506 | down(&tu->tread_sem); |
1470 | if (tu->timeri) { | 1507 | if (tu->timeri) { |
@@ -1478,7 +1515,8 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user * | |||
1478 | sprintf(str, "application %i", current->pid); | 1515 | sprintf(str, "application %i", current->pid); |
1479 | if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE) | 1516 | if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE) |
1480 | tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; | 1517 | tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; |
1481 | if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0) | 1518 | err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid); |
1519 | if (err < 0) | ||
1482 | goto __err; | 1520 | goto __err; |
1483 | 1521 | ||
1484 | kfree(tu->queue); | 1522 | kfree(tu->queue); |
@@ -1486,21 +1524,24 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user * | |||
1486 | kfree(tu->tqueue); | 1524 | kfree(tu->tqueue); |
1487 | tu->tqueue = NULL; | 1525 | tu->tqueue = NULL; |
1488 | if (tu->tread) { | 1526 | if (tu->tread) { |
1489 | tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL); | 1527 | tu->tqueue = kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), |
1528 | GFP_KERNEL); | ||
1490 | if (tu->tqueue == NULL) | 1529 | if (tu->tqueue == NULL) |
1491 | err = -ENOMEM; | 1530 | err = -ENOMEM; |
1492 | } else { | 1531 | } else { |
1493 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); | 1532 | tu->queue = kmalloc(tu->queue_size * sizeof(snd_timer_read_t), |
1533 | GFP_KERNEL); | ||
1494 | if (tu->queue == NULL) | 1534 | if (tu->queue == NULL) |
1495 | err = -ENOMEM; | 1535 | err = -ENOMEM; |
1496 | } | 1536 | } |
1497 | 1537 | ||
1498 | if (err < 0) { | 1538 | if (err < 0) { |
1499 | snd_timer_close(tu->timeri); | 1539 | snd_timer_close(tu->timeri); |
1500 | tu->timeri = NULL; | 1540 | tu->timeri = NULL; |
1501 | } else { | 1541 | } else { |
1502 | tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; | 1542 | tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; |
1503 | tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; | 1543 | tu->timeri->callback = tu->tread |
1544 | ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; | ||
1504 | tu->timeri->ccallback = snd_timer_user_ccallback; | 1545 | tu->timeri->ccallback = snd_timer_user_ccallback; |
1505 | tu->timeri->callback_data = (void *)tu; | 1546 | tu->timeri->callback_data = (void *)tu; |
1506 | } | 1547 | } |
@@ -1510,7 +1551,8 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user * | |||
1510 | return err; | 1551 | return err; |
1511 | } | 1552 | } |
1512 | 1553 | ||
1513 | static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info) | 1554 | static int snd_timer_user_info(struct file *file, |
1555 | snd_timer_info_t __user *_info) | ||
1514 | { | 1556 | { |
1515 | snd_timer_user_t *tu; | 1557 | snd_timer_user_t *tu; |
1516 | snd_timer_info_t *info; | 1558 | snd_timer_info_t *info; |
@@ -1537,7 +1579,8 @@ static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info | |||
1537 | return err; | 1579 | return err; |
1538 | } | 1580 | } |
1539 | 1581 | ||
1540 | static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_params) | 1582 | static int snd_timer_user_params(struct file *file, |
1583 | snd_timer_params_t __user *_params) | ||
1541 | { | 1584 | { |
1542 | snd_timer_user_t *tu; | 1585 | snd_timer_user_t *tu; |
1543 | snd_timer_params_t params; | 1586 | snd_timer_params_t params; |
@@ -1545,7 +1588,7 @@ static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_ | |||
1545 | snd_timer_read_t *tr; | 1588 | snd_timer_read_t *tr; |
1546 | snd_timer_tread_t *ttr; | 1589 | snd_timer_tread_t *ttr; |
1547 | int err; | 1590 | int err; |
1548 | 1591 | ||
1549 | tu = file->private_data; | 1592 | tu = file->private_data; |
1550 | snd_assert(tu->timeri != NULL, return -ENXIO); | 1593 | snd_assert(tu->timeri != NULL, return -ENXIO); |
1551 | t = tu->timeri->timer; | 1594 | t = tu->timeri->timer; |
@@ -1556,7 +1599,8 @@ static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_ | |||
1556 | err = -EINVAL; | 1599 | err = -EINVAL; |
1557 | goto _end; | 1600 | goto _end; |
1558 | } | 1601 | } |
1559 | if (params.queue_size > 0 && (params.queue_size < 32 || params.queue_size > 1024)) { | 1602 | if (params.queue_size > 0 && |
1603 | (params.queue_size < 32 || params.queue_size > 1024)) { | ||
1560 | err = -EINVAL; | 1604 | err = -EINVAL; |
1561 | goto _end; | 1605 | goto _end; |
1562 | } | 1606 | } |
@@ -1589,16 +1633,19 @@ static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_ | |||
1589 | if (params.flags & SNDRV_TIMER_PSFLG_EARLY_EVENT) | 1633 | if (params.flags & SNDRV_TIMER_PSFLG_EARLY_EVENT) |
1590 | tu->timeri->flags |= SNDRV_TIMER_IFLG_EARLY_EVENT; | 1634 | tu->timeri->flags |= SNDRV_TIMER_IFLG_EARLY_EVENT; |
1591 | spin_unlock_irq(&t->lock); | 1635 | spin_unlock_irq(&t->lock); |
1592 | if (params.queue_size > 0 && (unsigned int)tu->queue_size != params.queue_size) { | 1636 | if (params.queue_size > 0 && |
1637 | (unsigned int)tu->queue_size != params.queue_size) { | ||
1593 | if (tu->tread) { | 1638 | if (tu->tread) { |
1594 | ttr = (snd_timer_tread_t *)kmalloc(params.queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL); | 1639 | ttr = kmalloc(params.queue_size * sizeof(*ttr), |
1640 | GFP_KERNEL); | ||
1595 | if (ttr) { | 1641 | if (ttr) { |
1596 | kfree(tu->tqueue); | 1642 | kfree(tu->tqueue); |
1597 | tu->queue_size = params.queue_size; | 1643 | tu->queue_size = params.queue_size; |
1598 | tu->tqueue = ttr; | 1644 | tu->tqueue = ttr; |
1599 | } | 1645 | } |
1600 | } else { | 1646 | } else { |
1601 | tr = (snd_timer_read_t *)kmalloc(params.queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); | 1647 | tr = kmalloc(params.queue_size * sizeof(*tr), |
1648 | GFP_KERNEL); | ||
1602 | if (tr) { | 1649 | if (tr) { |
1603 | kfree(tu->queue); | 1650 | kfree(tu->queue); |
1604 | tu->queue_size = params.queue_size; | 1651 | tu->queue_size = params.queue_size; |
@@ -1622,7 +1669,6 @@ static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_ | |||
1622 | tu->qused++; | 1669 | tu->qused++; |
1623 | tu->qtail++; | 1670 | tu->qtail++; |
1624 | } | 1671 | } |
1625 | |||
1626 | } | 1672 | } |
1627 | tu->filter = params.filter; | 1673 | tu->filter = params.filter; |
1628 | tu->ticks = params.ticks; | 1674 | tu->ticks = params.ticks; |
@@ -1633,11 +1679,12 @@ static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_ | |||
1633 | return err; | 1679 | return err; |
1634 | } | 1680 | } |
1635 | 1681 | ||
1636 | static int snd_timer_user_status(struct file *file, snd_timer_status_t __user *_status) | 1682 | static int snd_timer_user_status(struct file *file, |
1683 | snd_timer_status_t __user *_status) | ||
1637 | { | 1684 | { |
1638 | snd_timer_user_t *tu; | 1685 | snd_timer_user_t *tu; |
1639 | snd_timer_status_t status; | 1686 | snd_timer_status_t status; |
1640 | 1687 | ||
1641 | tu = file->private_data; | 1688 | tu = file->private_data; |
1642 | snd_assert(tu->timeri != NULL, return -ENXIO); | 1689 | snd_assert(tu->timeri != NULL, return -ENXIO); |
1643 | memset(&status, 0, sizeof(status)); | 1690 | memset(&status, 0, sizeof(status)); |
@@ -1657,7 +1704,7 @@ static int snd_timer_user_start(struct file *file) | |||
1657 | { | 1704 | { |
1658 | int err; | 1705 | int err; |
1659 | snd_timer_user_t *tu; | 1706 | snd_timer_user_t *tu; |
1660 | 1707 | ||
1661 | tu = file->private_data; | 1708 | tu = file->private_data; |
1662 | snd_assert(tu->timeri != NULL, return -ENXIO); | 1709 | snd_assert(tu->timeri != NULL, return -ENXIO); |
1663 | snd_timer_stop(tu->timeri); | 1710 | snd_timer_stop(tu->timeri); |
@@ -1670,7 +1717,7 @@ static int snd_timer_user_stop(struct file *file) | |||
1670 | { | 1717 | { |
1671 | int err; | 1718 | int err; |
1672 | snd_timer_user_t *tu; | 1719 | snd_timer_user_t *tu; |
1673 | 1720 | ||
1674 | tu = file->private_data; | 1721 | tu = file->private_data; |
1675 | snd_assert(tu->timeri != NULL, return -ENXIO); | 1722 | snd_assert(tu->timeri != NULL, return -ENXIO); |
1676 | return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0; | 1723 | return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0; |
@@ -1680,7 +1727,7 @@ static int snd_timer_user_continue(struct file *file) | |||
1680 | { | 1727 | { |
1681 | int err; | 1728 | int err; |
1682 | snd_timer_user_t *tu; | 1729 | snd_timer_user_t *tu; |
1683 | 1730 | ||
1684 | tu = file->private_data; | 1731 | tu = file->private_data; |
1685 | snd_assert(tu->timeri != NULL, return -ENXIO); | 1732 | snd_assert(tu->timeri != NULL, return -ENXIO); |
1686 | tu->timeri->lost = 0; | 1733 | tu->timeri->lost = 0; |
@@ -1691,7 +1738,7 @@ static int snd_timer_user_pause(struct file *file) | |||
1691 | { | 1738 | { |
1692 | int err; | 1739 | int err; |
1693 | snd_timer_user_t *tu; | 1740 | snd_timer_user_t *tu; |
1694 | 1741 | ||
1695 | tu = file->private_data; | 1742 | tu = file->private_data; |
1696 | snd_assert(tu->timeri != NULL, return -ENXIO); | 1743 | snd_assert(tu->timeri != NULL, return -ENXIO); |
1697 | return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0; | 1744 | return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0; |
@@ -1704,12 +1751,13 @@ enum { | |||
1704 | SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23), | 1751 | SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23), |
1705 | }; | 1752 | }; |
1706 | 1753 | ||
1707 | static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 1754 | static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, |
1755 | unsigned long arg) | ||
1708 | { | 1756 | { |
1709 | snd_timer_user_t *tu; | 1757 | snd_timer_user_t *tu; |
1710 | void __user *argp = (void __user *)arg; | 1758 | void __user *argp = (void __user *)arg; |
1711 | int __user *p = argp; | 1759 | int __user *p = argp; |
1712 | 1760 | ||
1713 | tu = file->private_data; | 1761 | tu = file->private_data; |
1714 | switch (cmd) { | 1762 | switch (cmd) { |
1715 | case SNDRV_TIMER_IOCTL_PVERSION: | 1763 | case SNDRV_TIMER_IOCTL_PVERSION: |
@@ -1719,7 +1767,7 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l | |||
1719 | case SNDRV_TIMER_IOCTL_TREAD: | 1767 | case SNDRV_TIMER_IOCTL_TREAD: |
1720 | { | 1768 | { |
1721 | int xarg; | 1769 | int xarg; |
1722 | 1770 | ||
1723 | down(&tu->tread_sem); | 1771 | down(&tu->tread_sem); |
1724 | if (tu->timeri) { /* too late */ | 1772 | if (tu->timeri) { /* too late */ |
1725 | up(&tu->tread_sem); | 1773 | up(&tu->tread_sem); |
@@ -1767,7 +1815,7 @@ static int snd_timer_user_fasync(int fd, struct file * file, int on) | |||
1767 | { | 1815 | { |
1768 | snd_timer_user_t *tu; | 1816 | snd_timer_user_t *tu; |
1769 | int err; | 1817 | int err; |
1770 | 1818 | ||
1771 | tu = file->private_data; | 1819 | tu = file->private_data; |
1772 | err = fasync_helper(fd, file, on, &tu->fasync); | 1820 | err = fasync_helper(fd, file, on, &tu->fasync); |
1773 | if (err < 0) | 1821 | if (err < 0) |
@@ -1775,12 +1823,13 @@ static int snd_timer_user_fasync(int fd, struct file * file, int on) | |||
1775 | return 0; | 1823 | return 0; |
1776 | } | 1824 | } |
1777 | 1825 | ||
1778 | static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, size_t count, loff_t *offset) | 1826 | static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, |
1827 | size_t count, loff_t *offset) | ||
1779 | { | 1828 | { |
1780 | snd_timer_user_t *tu; | 1829 | snd_timer_user_t *tu; |
1781 | long result = 0, unit; | 1830 | long result = 0, unit; |
1782 | int err = 0; | 1831 | int err = 0; |
1783 | 1832 | ||
1784 | tu = file->private_data; | 1833 | tu = file->private_data; |
1785 | unit = tu->tread ? sizeof(snd_timer_tread_t) : sizeof(snd_timer_read_t); | 1834 | unit = tu->tread ? sizeof(snd_timer_tread_t) : sizeof(snd_timer_read_t); |
1786 | spin_lock_irq(&tu->qlock); | 1835 | spin_lock_irq(&tu->qlock); |
@@ -1814,12 +1863,14 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, size_ | |||
1814 | goto _error; | 1863 | goto _error; |
1815 | 1864 | ||
1816 | if (tu->tread) { | 1865 | if (tu->tread) { |
1817 | if (copy_to_user(buffer, &tu->tqueue[tu->qhead++], sizeof(snd_timer_tread_t))) { | 1866 | if (copy_to_user(buffer, &tu->tqueue[tu->qhead++], |
1867 | sizeof(snd_timer_tread_t))) { | ||
1818 | err = -EFAULT; | 1868 | err = -EFAULT; |
1819 | goto _error; | 1869 | goto _error; |
1820 | } | 1870 | } |
1821 | } else { | 1871 | } else { |
1822 | if (copy_to_user(buffer, &tu->queue[tu->qhead++], sizeof(snd_timer_read_t))) { | 1872 | if (copy_to_user(buffer, &tu->queue[tu->qhead++], |
1873 | sizeof(snd_timer_read_t))) { | ||
1823 | err = -EFAULT; | 1874 | err = -EFAULT; |
1824 | goto _error; | 1875 | goto _error; |
1825 | } | 1876 | } |
@@ -1846,7 +1897,7 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait) | |||
1846 | tu = file->private_data; | 1897 | tu = file->private_data; |
1847 | 1898 | ||
1848 | poll_wait(file, &tu->qchange_sleep, wait); | 1899 | poll_wait(file, &tu->qchange_sleep, wait); |
1849 | 1900 | ||
1850 | mask = 0; | 1901 | mask = 0; |
1851 | if (tu->qused) | 1902 | if (tu->qused) |
1852 | mask |= POLLIN | POLLRDNORM; | 1903 | mask |= POLLIN | POLLRDNORM; |
@@ -1890,9 +1941,11 @@ static int __init alsa_timer_init(void) | |||
1890 | snd_info_entry_t *entry; | 1941 | snd_info_entry_t *entry; |
1891 | 1942 | ||
1892 | #ifdef SNDRV_OSS_INFO_DEV_TIMERS | 1943 | #ifdef SNDRV_OSS_INFO_DEV_TIMERS |
1893 | snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1, "system timer"); | 1944 | snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1, |
1945 | "system timer"); | ||
1894 | #endif | 1946 | #endif |
1895 | if ((entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL)) != NULL) { | 1947 | entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL); |
1948 | if (entry != NULL) { | ||
1896 | entry->c.text.read_size = SNDRV_TIMER_DEVICES * 128; | 1949 | entry->c.text.read_size = SNDRV_TIMER_DEVICES * 128; |
1897 | entry->c.text.read = snd_timer_proc_read; | 1950 | entry->c.text.read = snd_timer_proc_read; |
1898 | if (snd_info_register(entry) < 0) { | 1951 | if (snd_info_register(entry) < 0) { |
@@ -1902,10 +1955,12 @@ static int __init alsa_timer_init(void) | |||
1902 | } | 1955 | } |
1903 | snd_timer_proc_entry = entry; | 1956 | snd_timer_proc_entry = entry; |
1904 | if ((err = snd_timer_register_system()) < 0) | 1957 | if ((err = snd_timer_register_system()) < 0) |
1905 | snd_printk(KERN_ERR "unable to register system timer (%i)\n", err); | 1958 | snd_printk(KERN_ERR "unable to register system timer (%i)\n", |
1959 | err); | ||
1906 | if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, | 1960 | if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, |
1907 | NULL, 0, &snd_timer_reg, "timer"))<0) | 1961 | NULL, 0, &snd_timer_reg, "timer"))<0) |
1908 | snd_printk(KERN_ERR "unable to register timer device (%i)\n", err); | 1962 | snd_printk(KERN_ERR "unable to register timer device (%i)\n", |
1963 | err); | ||
1909 | return 0; | 1964 | return 0; |
1910 | } | 1965 | } |
1911 | 1966 | ||