diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2014-11-28 10:59:16 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-11-29 14:08:19 -0500 |
commit | 19af57b46dda93b34902739673d5f37d8c6d0d5f (patch) | |
tree | 6eb983feabcefeea8dd0834a4b3caf95ba496995 /sound/firewire | |
parent | c50fb91f53626e3bdae3ffebfee586786f970f7c (diff) |
ALSA: dice: Split hwdep functionality into a file
This commit adds a file and move some codes related to hwdep functionality.
This interface is designed for mixer/control application. By using hwdep
interface, the application can get information about firewire node, can
lock/unlock kernel streaming and can get notification at starting/stopping
kernel streaming.
Additionally, this interface give a way to read Dice notification.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire')
-rw-r--r-- | sound/firewire/dice/Makefile | 3 | ||||
-rw-r--r-- | sound/firewire/dice/dice-hwdep.c | 190 | ||||
-rw-r--r-- | sound/firewire/dice/dice.c | 182 | ||||
-rw-r--r-- | sound/firewire/dice/dice.h | 2 |
4 files changed, 195 insertions, 182 deletions
diff --git a/sound/firewire/dice/Makefile b/sound/firewire/dice/Makefile index 1ddaeca9a137..73b0e38803cb 100644 --- a/sound/firewire/dice/Makefile +++ b/sound/firewire/dice/Makefile | |||
@@ -1,2 +1,3 @@ | |||
1 | snd-dice-objs := dice-transaction.o dice-stream.o dice-pcm.o dice.o | 1 | snd-dice-objs := dice-transaction.o dice-stream.o dice-pcm.o dice-hwdep.o \ |
2 | dice.o | ||
2 | obj-m += snd-dice.o | 3 | obj-m += snd-dice.o |
diff --git a/sound/firewire/dice/dice-hwdep.c b/sound/firewire/dice/dice-hwdep.c new file mode 100644 index 000000000000..a4dc02a86f12 --- /dev/null +++ b/sound/firewire/dice/dice-hwdep.c | |||
@@ -0,0 +1,190 @@ | |||
1 | /* | ||
2 | * dice_hwdep.c - a part of driver for DICE based devices | ||
3 | * | ||
4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | ||
5 | * Copyright (c) 2014 Takashi Sakamoto <o-takashi@sakamocchi.jp> | ||
6 | * | ||
7 | * Licensed under the terms of the GNU General Public License, version 2. | ||
8 | */ | ||
9 | |||
10 | #include "dice.h" | ||
11 | |||
12 | static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, | ||
13 | long count, loff_t *offset) | ||
14 | { | ||
15 | struct snd_dice *dice = hwdep->private_data; | ||
16 | DEFINE_WAIT(wait); | ||
17 | union snd_firewire_event event; | ||
18 | |||
19 | spin_lock_irq(&dice->lock); | ||
20 | |||
21 | while (!dice->dev_lock_changed && dice->notification_bits == 0) { | ||
22 | prepare_to_wait(&dice->hwdep_wait, &wait, TASK_INTERRUPTIBLE); | ||
23 | spin_unlock_irq(&dice->lock); | ||
24 | schedule(); | ||
25 | finish_wait(&dice->hwdep_wait, &wait); | ||
26 | if (signal_pending(current)) | ||
27 | return -ERESTARTSYS; | ||
28 | spin_lock_irq(&dice->lock); | ||
29 | } | ||
30 | |||
31 | memset(&event, 0, sizeof(event)); | ||
32 | if (dice->dev_lock_changed) { | ||
33 | event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; | ||
34 | event.lock_status.status = dice->dev_lock_count > 0; | ||
35 | dice->dev_lock_changed = false; | ||
36 | |||
37 | count = min_t(long, count, sizeof(event.lock_status)); | ||
38 | } else { | ||
39 | event.dice_notification.type = | ||
40 | SNDRV_FIREWIRE_EVENT_DICE_NOTIFICATION; | ||
41 | event.dice_notification.notification = dice->notification_bits; | ||
42 | dice->notification_bits = 0; | ||
43 | |||
44 | count = min_t(long, count, sizeof(event.dice_notification)); | ||
45 | } | ||
46 | |||
47 | spin_unlock_irq(&dice->lock); | ||
48 | |||
49 | if (copy_to_user(buf, &event, count)) | ||
50 | return -EFAULT; | ||
51 | |||
52 | return count; | ||
53 | } | ||
54 | |||
55 | static unsigned int hwdep_poll(struct snd_hwdep *hwdep, struct file *file, | ||
56 | poll_table *wait) | ||
57 | { | ||
58 | struct snd_dice *dice = hwdep->private_data; | ||
59 | unsigned int events; | ||
60 | |||
61 | poll_wait(file, &dice->hwdep_wait, wait); | ||
62 | |||
63 | spin_lock_irq(&dice->lock); | ||
64 | if (dice->dev_lock_changed || dice->notification_bits != 0) | ||
65 | events = POLLIN | POLLRDNORM; | ||
66 | else | ||
67 | events = 0; | ||
68 | spin_unlock_irq(&dice->lock); | ||
69 | |||
70 | return events; | ||
71 | } | ||
72 | |||
73 | static int hwdep_get_info(struct snd_dice *dice, void __user *arg) | ||
74 | { | ||
75 | struct fw_device *dev = fw_parent_device(dice->unit); | ||
76 | struct snd_firewire_get_info info; | ||
77 | |||
78 | memset(&info, 0, sizeof(info)); | ||
79 | info.type = SNDRV_FIREWIRE_TYPE_DICE; | ||
80 | info.card = dev->card->index; | ||
81 | *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); | ||
82 | *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); | ||
83 | strlcpy(info.device_name, dev_name(&dev->device), | ||
84 | sizeof(info.device_name)); | ||
85 | |||
86 | if (copy_to_user(arg, &info, sizeof(info))) | ||
87 | return -EFAULT; | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static int hwdep_lock(struct snd_dice *dice) | ||
93 | { | ||
94 | int err; | ||
95 | |||
96 | spin_lock_irq(&dice->lock); | ||
97 | |||
98 | if (dice->dev_lock_count == 0) { | ||
99 | dice->dev_lock_count = -1; | ||
100 | err = 0; | ||
101 | } else { | ||
102 | err = -EBUSY; | ||
103 | } | ||
104 | |||
105 | spin_unlock_irq(&dice->lock); | ||
106 | |||
107 | return err; | ||
108 | } | ||
109 | |||
110 | static int hwdep_unlock(struct snd_dice *dice) | ||
111 | { | ||
112 | int err; | ||
113 | |||
114 | spin_lock_irq(&dice->lock); | ||
115 | |||
116 | if (dice->dev_lock_count == -1) { | ||
117 | dice->dev_lock_count = 0; | ||
118 | err = 0; | ||
119 | } else { | ||
120 | err = -EBADFD; | ||
121 | } | ||
122 | |||
123 | spin_unlock_irq(&dice->lock); | ||
124 | |||
125 | return err; | ||
126 | } | ||
127 | |||
128 | static int hwdep_release(struct snd_hwdep *hwdep, struct file *file) | ||
129 | { | ||
130 | struct snd_dice *dice = hwdep->private_data; | ||
131 | |||
132 | spin_lock_irq(&dice->lock); | ||
133 | if (dice->dev_lock_count == -1) | ||
134 | dice->dev_lock_count = 0; | ||
135 | spin_unlock_irq(&dice->lock); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static int hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file, | ||
141 | unsigned int cmd, unsigned long arg) | ||
142 | { | ||
143 | struct snd_dice *dice = hwdep->private_data; | ||
144 | |||
145 | switch (cmd) { | ||
146 | case SNDRV_FIREWIRE_IOCTL_GET_INFO: | ||
147 | return hwdep_get_info(dice, (void __user *)arg); | ||
148 | case SNDRV_FIREWIRE_IOCTL_LOCK: | ||
149 | return hwdep_lock(dice); | ||
150 | case SNDRV_FIREWIRE_IOCTL_UNLOCK: | ||
151 | return hwdep_unlock(dice); | ||
152 | default: | ||
153 | return -ENOIOCTLCMD; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | #ifdef CONFIG_COMPAT | ||
158 | static int hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file, | ||
159 | unsigned int cmd, unsigned long arg) | ||
160 | { | ||
161 | return hwdep_ioctl(hwdep, file, cmd, | ||
162 | (unsigned long)compat_ptr(arg)); | ||
163 | } | ||
164 | #else | ||
165 | #define hwdep_compat_ioctl NULL | ||
166 | #endif | ||
167 | |||
168 | int snd_dice_create_hwdep(struct snd_dice *dice) | ||
169 | { | ||
170 | static const struct snd_hwdep_ops ops = { | ||
171 | .read = hwdep_read, | ||
172 | .release = hwdep_release, | ||
173 | .poll = hwdep_poll, | ||
174 | .ioctl = hwdep_ioctl, | ||
175 | .ioctl_compat = hwdep_compat_ioctl, | ||
176 | }; | ||
177 | struct snd_hwdep *hwdep; | ||
178 | int err; | ||
179 | |||
180 | err = snd_hwdep_new(dice->card, "DICE", 0, &hwdep); | ||
181 | if (err < 0) | ||
182 | return err; | ||
183 | strcpy(hwdep->name, "DICE"); | ||
184 | hwdep->iface = SNDRV_HWDEP_IFACE_FW_DICE; | ||
185 | hwdep->ops = ops; | ||
186 | hwdep->private_data = dice; | ||
187 | hwdep->exclusive = true; | ||
188 | |||
189 | return 0; | ||
190 | } | ||
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index b76ed06e5c4d..dbc1239c95ee 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c | |||
@@ -11,186 +11,6 @@ MODULE_DESCRIPTION("DICE driver"); | |||
11 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | 11 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); |
12 | MODULE_LICENSE("GPL v2"); | 12 | MODULE_LICENSE("GPL v2"); |
13 | 13 | ||
14 | static long dice_hwdep_read(struct snd_hwdep *hwdep, char __user *buf, | ||
15 | long count, loff_t *offset) | ||
16 | { | ||
17 | struct snd_dice *dice = hwdep->private_data; | ||
18 | DEFINE_WAIT(wait); | ||
19 | union snd_firewire_event event; | ||
20 | |||
21 | spin_lock_irq(&dice->lock); | ||
22 | |||
23 | while (!dice->dev_lock_changed && dice->notification_bits == 0) { | ||
24 | prepare_to_wait(&dice->hwdep_wait, &wait, TASK_INTERRUPTIBLE); | ||
25 | spin_unlock_irq(&dice->lock); | ||
26 | schedule(); | ||
27 | finish_wait(&dice->hwdep_wait, &wait); | ||
28 | if (signal_pending(current)) | ||
29 | return -ERESTARTSYS; | ||
30 | spin_lock_irq(&dice->lock); | ||
31 | } | ||
32 | |||
33 | memset(&event, 0, sizeof(event)); | ||
34 | if (dice->dev_lock_changed) { | ||
35 | event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; | ||
36 | event.lock_status.status = dice->dev_lock_count > 0; | ||
37 | dice->dev_lock_changed = false; | ||
38 | |||
39 | count = min_t(long, count, sizeof(event.lock_status)); | ||
40 | } else { | ||
41 | event.dice_notification.type = | ||
42 | SNDRV_FIREWIRE_EVENT_DICE_NOTIFICATION; | ||
43 | event.dice_notification.notification = dice->notification_bits; | ||
44 | dice->notification_bits = 0; | ||
45 | |||
46 | count = min_t(long, count, sizeof(event.dice_notification)); | ||
47 | } | ||
48 | |||
49 | spin_unlock_irq(&dice->lock); | ||
50 | |||
51 | if (copy_to_user(buf, &event, count)) | ||
52 | return -EFAULT; | ||
53 | |||
54 | return count; | ||
55 | } | ||
56 | |||
57 | static unsigned int dice_hwdep_poll(struct snd_hwdep *hwdep, struct file *file, | ||
58 | poll_table *wait) | ||
59 | { | ||
60 | struct snd_dice *dice = hwdep->private_data; | ||
61 | unsigned int events; | ||
62 | |||
63 | poll_wait(file, &dice->hwdep_wait, wait); | ||
64 | |||
65 | spin_lock_irq(&dice->lock); | ||
66 | if (dice->dev_lock_changed || dice->notification_bits != 0) | ||
67 | events = POLLIN | POLLRDNORM; | ||
68 | else | ||
69 | events = 0; | ||
70 | spin_unlock_irq(&dice->lock); | ||
71 | |||
72 | return events; | ||
73 | } | ||
74 | |||
75 | static int dice_hwdep_get_info(struct snd_dice *dice, void __user *arg) | ||
76 | { | ||
77 | struct fw_device *dev = fw_parent_device(dice->unit); | ||
78 | struct snd_firewire_get_info info; | ||
79 | |||
80 | memset(&info, 0, sizeof(info)); | ||
81 | info.type = SNDRV_FIREWIRE_TYPE_DICE; | ||
82 | info.card = dev->card->index; | ||
83 | *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); | ||
84 | *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); | ||
85 | strlcpy(info.device_name, dev_name(&dev->device), | ||
86 | sizeof(info.device_name)); | ||
87 | |||
88 | if (copy_to_user(arg, &info, sizeof(info))) | ||
89 | return -EFAULT; | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static int dice_hwdep_lock(struct snd_dice *dice) | ||
95 | { | ||
96 | int err; | ||
97 | |||
98 | spin_lock_irq(&dice->lock); | ||
99 | |||
100 | if (dice->dev_lock_count == 0) { | ||
101 | dice->dev_lock_count = -1; | ||
102 | err = 0; | ||
103 | } else { | ||
104 | err = -EBUSY; | ||
105 | } | ||
106 | |||
107 | spin_unlock_irq(&dice->lock); | ||
108 | |||
109 | return err; | ||
110 | } | ||
111 | |||
112 | static int dice_hwdep_unlock(struct snd_dice *dice) | ||
113 | { | ||
114 | int err; | ||
115 | |||
116 | spin_lock_irq(&dice->lock); | ||
117 | |||
118 | if (dice->dev_lock_count == -1) { | ||
119 | dice->dev_lock_count = 0; | ||
120 | err = 0; | ||
121 | } else { | ||
122 | err = -EBADFD; | ||
123 | } | ||
124 | |||
125 | spin_unlock_irq(&dice->lock); | ||
126 | |||
127 | return err; | ||
128 | } | ||
129 | |||
130 | static int dice_hwdep_release(struct snd_hwdep *hwdep, struct file *file) | ||
131 | { | ||
132 | struct snd_dice *dice = hwdep->private_data; | ||
133 | |||
134 | spin_lock_irq(&dice->lock); | ||
135 | if (dice->dev_lock_count == -1) | ||
136 | dice->dev_lock_count = 0; | ||
137 | spin_unlock_irq(&dice->lock); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int dice_hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file, | ||
143 | unsigned int cmd, unsigned long arg) | ||
144 | { | ||
145 | struct snd_dice *dice = hwdep->private_data; | ||
146 | |||
147 | switch (cmd) { | ||
148 | case SNDRV_FIREWIRE_IOCTL_GET_INFO: | ||
149 | return dice_hwdep_get_info(dice, (void __user *)arg); | ||
150 | case SNDRV_FIREWIRE_IOCTL_LOCK: | ||
151 | return dice_hwdep_lock(dice); | ||
152 | case SNDRV_FIREWIRE_IOCTL_UNLOCK: | ||
153 | return dice_hwdep_unlock(dice); | ||
154 | default: | ||
155 | return -ENOIOCTLCMD; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | #ifdef CONFIG_COMPAT | ||
160 | static int dice_hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file, | ||
161 | unsigned int cmd, unsigned long arg) | ||
162 | { | ||
163 | return dice_hwdep_ioctl(hwdep, file, cmd, | ||
164 | (unsigned long)compat_ptr(arg)); | ||
165 | } | ||
166 | #else | ||
167 | #define dice_hwdep_compat_ioctl NULL | ||
168 | #endif | ||
169 | |||
170 | static int dice_create_hwdep(struct snd_dice *dice) | ||
171 | { | ||
172 | static const struct snd_hwdep_ops ops = { | ||
173 | .read = dice_hwdep_read, | ||
174 | .release = dice_hwdep_release, | ||
175 | .poll = dice_hwdep_poll, | ||
176 | .ioctl = dice_hwdep_ioctl, | ||
177 | .ioctl_compat = dice_hwdep_compat_ioctl, | ||
178 | }; | ||
179 | struct snd_hwdep *hwdep; | ||
180 | int err; | ||
181 | |||
182 | err = snd_hwdep_new(dice->card, "DICE", 0, &hwdep); | ||
183 | if (err < 0) | ||
184 | return err; | ||
185 | strcpy(hwdep->name, "DICE"); | ||
186 | hwdep->iface = SNDRV_HWDEP_IFACE_FW_DICE; | ||
187 | hwdep->ops = ops; | ||
188 | hwdep->private_data = dice; | ||
189 | hwdep->exclusive = true; | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static int dice_proc_read_mem(struct snd_dice *dice, void *buffer, | 14 | static int dice_proc_read_mem(struct snd_dice *dice, void *buffer, |
195 | unsigned int offset_q, unsigned int quadlets) | 15 | unsigned int offset_q, unsigned int quadlets) |
196 | { | 16 | { |
@@ -696,7 +516,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) | |||
696 | if (err < 0) | 516 | if (err < 0) |
697 | goto error; | 517 | goto error; |
698 | 518 | ||
699 | err = dice_create_hwdep(dice); | 519 | err = snd_dice_create_hwdep(dice); |
700 | if (err < 0) | 520 | if (err < 0) |
701 | goto error; | 521 | goto error; |
702 | 522 | ||
diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h index 4d9e55ba895b..dcc8c789cd43 100644 --- a/sound/firewire/dice/dice.h +++ b/sound/firewire/dice/dice.h | |||
@@ -173,4 +173,6 @@ void snd_dice_stream_lock_release(struct snd_dice *dice); | |||
173 | 173 | ||
174 | int snd_dice_create_pcm(struct snd_dice *dice); | 174 | int snd_dice_create_pcm(struct snd_dice *dice); |
175 | 175 | ||
176 | int snd_dice_create_hwdep(struct snd_dice *dice); | ||
177 | |||
176 | #endif | 178 | #endif |