diff options
Diffstat (limited to 'sound/core/timer.c')
| -rw-r--r-- | sound/core/timer.c | 100 |
1 files changed, 65 insertions, 35 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c index fa762ca439be..b498e5482d77 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
| @@ -69,6 +69,7 @@ typedef struct { | |||
| 69 | struct timespec tstamp; /* trigger tstamp */ | 69 | struct timespec tstamp; /* trigger tstamp */ |
| 70 | wait_queue_head_t qchange_sleep; | 70 | wait_queue_head_t qchange_sleep; |
| 71 | struct fasync_struct *fasync; | 71 | struct fasync_struct *fasync; |
| 72 | struct semaphore tread_sem; | ||
| 72 | } snd_timer_user_t; | 73 | } snd_timer_user_t; |
| 73 | 74 | ||
| 74 | /* list of timers */ | 75 | /* list of timers */ |
| @@ -844,7 +845,7 @@ int snd_timer_dev_register(snd_device_t *dev) | |||
| 844 | return 0; | 845 | return 0; |
| 845 | } | 846 | } |
| 846 | 847 | ||
| 847 | int snd_timer_unregister(snd_timer_t *timer) | 848 | static int snd_timer_unregister(snd_timer_t *timer) |
| 848 | { | 849 | { |
| 849 | struct list_head *p, *n; | 850 | struct list_head *p, *n; |
| 850 | snd_timer_instance_t *ti; | 851 | snd_timer_instance_t *ti; |
| @@ -945,11 +946,6 @@ struct snd_timer_system_private { | |||
| 945 | unsigned long correction; | 946 | unsigned long correction; |
| 946 | }; | 947 | }; |
| 947 | 948 | ||
| 948 | unsigned int snd_timer_system_resolution(void) | ||
| 949 | { | ||
| 950 | return 1000000000L / HZ; | ||
| 951 | } | ||
| 952 | |||
| 953 | static void snd_timer_s_function(unsigned long data) | 949 | static void snd_timer_s_function(unsigned long data) |
| 954 | { | 950 | { |
| 955 | snd_timer_t *timer = (snd_timer_t *)data; | 951 | snd_timer_t *timer = (snd_timer_t *)data; |
| @@ -1208,6 +1204,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file) | |||
| 1208 | return -ENOMEM; | 1204 | return -ENOMEM; |
| 1209 | spin_lock_init(&tu->qlock); | 1205 | spin_lock_init(&tu->qlock); |
| 1210 | init_waitqueue_head(&tu->qchange_sleep); | 1206 | init_waitqueue_head(&tu->qchange_sleep); |
| 1207 | init_MUTEX(&tu->tread_sem); | ||
| 1211 | tu->ticks = 1; | 1208 | tu->ticks = 1; |
| 1212 | tu->queue_size = 128; | 1209 | tu->queue_size = 128; |
| 1213 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); | 1210 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); |
| @@ -1454,46 +1451,51 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user * | |||
| 1454 | snd_timer_user_t *tu; | 1451 | snd_timer_user_t *tu; |
| 1455 | snd_timer_select_t tselect; | 1452 | snd_timer_select_t tselect; |
| 1456 | char str[32]; | 1453 | char str[32]; |
| 1457 | int err; | 1454 | int err = 0; |
| 1458 | 1455 | ||
| 1459 | tu = file->private_data; | 1456 | tu = file->private_data; |
| 1460 | if (tu->timeri) | 1457 | down(&tu->tread_sem); |
| 1458 | if (tu->timeri) { | ||
| 1461 | snd_timer_close(tu->timeri); | 1459 | snd_timer_close(tu->timeri); |
| 1462 | if (copy_from_user(&tselect, _tselect, sizeof(tselect))) | 1460 | tu->timeri = NULL; |
| 1463 | return -EFAULT; | 1461 | } |
| 1462 | if (copy_from_user(&tselect, _tselect, sizeof(tselect))) { | ||
| 1463 | err = -EFAULT; | ||
| 1464 | goto __err; | ||
| 1465 | } | ||
| 1464 | sprintf(str, "application %i", current->pid); | 1466 | sprintf(str, "application %i", current->pid); |
| 1465 | if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE) | 1467 | if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE) |
| 1466 | tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; | 1468 | tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; |
| 1467 | if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0) | 1469 | if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0) |
| 1468 | return err; | 1470 | goto __err; |
| 1469 | 1471 | ||
| 1470 | if (tu->queue) { | 1472 | kfree(tu->queue); |
| 1471 | kfree(tu->queue); | 1473 | tu->queue = NULL; |
| 1472 | tu->queue = NULL; | 1474 | kfree(tu->tqueue); |
| 1473 | } | 1475 | tu->tqueue = NULL; |
| 1474 | if (tu->tqueue) { | ||
| 1475 | kfree(tu->tqueue); | ||
| 1476 | tu->tqueue = NULL; | ||
| 1477 | } | ||
| 1478 | if (tu->tread) { | 1476 | if (tu->tread) { |
| 1479 | tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL); | 1477 | tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL); |
| 1480 | if (tu->tqueue == NULL) { | 1478 | if (tu->tqueue == NULL) |
| 1481 | snd_timer_close(tu->timeri); | 1479 | err = -ENOMEM; |
| 1482 | return -ENOMEM; | ||
| 1483 | } | ||
| 1484 | } else { | 1480 | } else { |
| 1485 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); | 1481 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); |
| 1486 | if (tu->queue == NULL) { | 1482 | if (tu->queue == NULL) |
| 1487 | snd_timer_close(tu->timeri); | 1483 | err = -ENOMEM; |
| 1488 | return -ENOMEM; | ||
| 1489 | } | ||
| 1490 | } | 1484 | } |
| 1491 | 1485 | ||
| 1492 | tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; | 1486 | if (err < 0) { |
| 1493 | tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; | 1487 | snd_timer_close(tu->timeri); |
| 1494 | tu->timeri->ccallback = snd_timer_user_ccallback; | 1488 | tu->timeri = NULL; |
| 1495 | tu->timeri->callback_data = (void *)tu; | 1489 | } else { |
| 1496 | return 0; | 1490 | tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; |
| 1491 | tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; | ||
| 1492 | tu->timeri->ccallback = snd_timer_user_ccallback; | ||
| 1493 | tu->timeri->callback_data = (void *)tu; | ||
| 1494 | } | ||
| 1495 | |||
| 1496 | __err: | ||
| 1497 | up(&tu->tread_sem); | ||
| 1498 | return err; | ||
| 1497 | } | 1499 | } |
| 1498 | 1500 | ||
| 1499 | static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info) | 1501 | static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info) |
| @@ -1669,6 +1671,23 @@ static int snd_timer_user_continue(struct file *file) | |||
| 1669 | return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; | 1671 | return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; |
| 1670 | } | 1672 | } |
| 1671 | 1673 | ||
| 1674 | static int snd_timer_user_pause(struct file *file) | ||
| 1675 | { | ||
| 1676 | int err; | ||
| 1677 | snd_timer_user_t *tu; | ||
| 1678 | |||
| 1679 | tu = file->private_data; | ||
| 1680 | snd_assert(tu->timeri != NULL, return -ENXIO); | ||
| 1681 | return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0; | ||
| 1682 | } | ||
| 1683 | |||
| 1684 | enum { | ||
| 1685 | SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20), | ||
| 1686 | SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21), | ||
| 1687 | SNDRV_TIMER_IOCTL_CONTINUE_OLD = _IO('T', 0x22), | ||
| 1688 | SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23), | ||
| 1689 | }; | ||
| 1690 | |||
| 1672 | static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 1691 | static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 1673 | { | 1692 | { |
| 1674 | snd_timer_user_t *tu; | 1693 | snd_timer_user_t *tu; |
| @@ -1685,11 +1704,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l | |||
| 1685 | { | 1704 | { |
| 1686 | int xarg; | 1705 | int xarg; |
| 1687 | 1706 | ||
| 1688 | if (tu->timeri) /* too late */ | 1707 | down(&tu->tread_sem); |
| 1708 | if (tu->timeri) { /* too late */ | ||
| 1709 | up(&tu->tread_sem); | ||
| 1689 | return -EBUSY; | 1710 | return -EBUSY; |
| 1690 | if (get_user(xarg, p)) | 1711 | } |
| 1712 | if (get_user(xarg, p)) { | ||
| 1713 | up(&tu->tread_sem); | ||
| 1691 | return -EFAULT; | 1714 | return -EFAULT; |
| 1715 | } | ||
| 1692 | tu->tread = xarg ? 1 : 0; | 1716 | tu->tread = xarg ? 1 : 0; |
| 1717 | up(&tu->tread_sem); | ||
| 1693 | return 0; | 1718 | return 0; |
| 1694 | } | 1719 | } |
| 1695 | case SNDRV_TIMER_IOCTL_GINFO: | 1720 | case SNDRV_TIMER_IOCTL_GINFO: |
| @@ -1707,11 +1732,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l | |||
| 1707 | case SNDRV_TIMER_IOCTL_STATUS: | 1732 | case SNDRV_TIMER_IOCTL_STATUS: |
| 1708 | return snd_timer_user_status(file, argp); | 1733 | return snd_timer_user_status(file, argp); |
| 1709 | case SNDRV_TIMER_IOCTL_START: | 1734 | case SNDRV_TIMER_IOCTL_START: |
| 1735 | case SNDRV_TIMER_IOCTL_START_OLD: | ||
| 1710 | return snd_timer_user_start(file); | 1736 | return snd_timer_user_start(file); |
| 1711 | case SNDRV_TIMER_IOCTL_STOP: | 1737 | case SNDRV_TIMER_IOCTL_STOP: |
| 1738 | case SNDRV_TIMER_IOCTL_STOP_OLD: | ||
| 1712 | return snd_timer_user_stop(file); | 1739 | return snd_timer_user_stop(file); |
| 1713 | case SNDRV_TIMER_IOCTL_CONTINUE: | 1740 | case SNDRV_TIMER_IOCTL_CONTINUE: |
| 1741 | case SNDRV_TIMER_IOCTL_CONTINUE_OLD: | ||
| 1714 | return snd_timer_user_continue(file); | 1742 | return snd_timer_user_continue(file); |
| 1743 | case SNDRV_TIMER_IOCTL_PAUSE: | ||
| 1744 | case SNDRV_TIMER_IOCTL_PAUSE_OLD: | ||
| 1745 | return snd_timer_user_pause(file); | ||
| 1715 | } | 1746 | } |
| 1716 | return -ENOTTY; | 1747 | return -ENOTTY; |
| 1717 | } | 1748 | } |
| @@ -1898,4 +1929,3 @@ EXPORT_SYMBOL(snd_timer_global_free); | |||
| 1898 | EXPORT_SYMBOL(snd_timer_global_register); | 1929 | EXPORT_SYMBOL(snd_timer_global_register); |
| 1899 | EXPORT_SYMBOL(snd_timer_global_unregister); | 1930 | EXPORT_SYMBOL(snd_timer_global_unregister); |
| 1900 | EXPORT_SYMBOL(snd_timer_interrupt); | 1931 | EXPORT_SYMBOL(snd_timer_interrupt); |
| 1901 | EXPORT_SYMBOL(snd_timer_system_resolution); | ||
