ainstr_simple.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * Simple (MOD player) - Instrument routines
  3. * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. *
  19. */
  20. #include <sound/driver.h>
  21. #include <linux/init.h>
  22. #include <linux/sched.h>
  23. #include <linux/slab.h>
  24. #include <sound/core.h>
  25. #include <sound/ainstr_simple.h>
  26. #include <sound/initval.h>
  27. #include <asm/uaccess.h>
  28. MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
  29. MODULE_DESCRIPTION("Advanced Linux Sound Architecture Simple Instrument support.");
  30. MODULE_LICENSE("GPL");
  31. static unsigned int snd_seq_simple_size(unsigned int size, unsigned int format)
  32. {
  33. unsigned int result = size;
  34. if (format & SIMPLE_WAVE_16BIT)
  35. result <<= 1;
  36. if (format & SIMPLE_WAVE_STEREO)
  37. result <<= 1;
  38. return result;
  39. }
  40. static void snd_seq_simple_instr_free(struct snd_simple_ops *ops,
  41. struct simple_instrument *ip,
  42. int atomic)
  43. {
  44. if (ops->remove_sample)
  45. ops->remove_sample(ops->private_data, ip, atomic);
  46. }
  47. static int snd_seq_simple_put(void *private_data, struct snd_seq_kinstr *instr,
  48. char __user *instr_data, long len,
  49. int atomic, int cmd)
  50. {
  51. struct snd_simple_ops *ops = private_data;
  52. struct simple_instrument *ip;
  53. struct simple_xinstrument ix;
  54. int err;
  55. gfp_t gfp_mask;
  56. unsigned int real_size;
  57. if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
  58. return -EINVAL;
  59. gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
  60. /* copy instrument data */
  61. if (len < (long)sizeof(ix))
  62. return -EINVAL;
  63. if (copy_from_user(&ix, instr_data, sizeof(ix)))
  64. return -EFAULT;
  65. if (ix.stype != SIMPLE_STRU_INSTR)
  66. return -EINVAL;
  67. instr_data += sizeof(ix);
  68. len -= sizeof(ix);
  69. ip = (struct simple_instrument *)KINSTR_DATA(instr);
  70. ip->share_id[0] = le32_to_cpu(ix.share_id[0]);
  71. ip->share_id[1] = le32_to_cpu(ix.share_id[1]);
  72. ip->share_id[2] = le32_to_cpu(ix.share_id[2]);
  73. ip->share_id[3] = le32_to_cpu(ix.share_id[3]);
  74. ip->format = le32_to_cpu(ix.format);
  75. ip->size = le32_to_cpu(ix.size);
  76. ip->start = le32_to_cpu(ix.start);
  77. ip->loop_start = le32_to_cpu(ix.loop_start);
  78. ip->loop_end = le32_to_cpu(ix.loop_end);
  79. ip->loop_repeat = le16_to_cpu(ix.loop_repeat);
  80. ip->effect1 = ix.effect1;
  81. ip->effect1_depth = ix.effect1_depth;
  82. ip->effect2 = ix.effect2;
  83. ip->effect2_depth = ix.effect2_depth;
  84. real_size = snd_seq_simple_size(ip->size, ip->format);
  85. if (len < (long)real_size)
  86. return -EINVAL;
  87. if (ops->put_sample) {
  88. err = ops->put_sample(ops->private_data, ip,
  89. instr_data, real_size, atomic);
  90. if (err < 0)
  91. return err;
  92. }
  93. return 0;
  94. }
  95. static int snd_seq_simple_get(void *private_data, struct snd_seq_kinstr *instr,
  96. char __user *instr_data, long len,
  97. int atomic, int cmd)
  98. {
  99. struct snd_simple_ops *ops = private_data;
  100. struct simple_instrument *ip;
  101. struct simple_xinstrument ix;
  102. int err;
  103. unsigned int real_size;
  104. if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
  105. return -EINVAL;
  106. if (len < (long)sizeof(ix))
  107. return -ENOMEM;
  108. memset(&ix, 0, sizeof(ix));
  109. ip = (struct simple_instrument *)KINSTR_DATA(instr);
  110. ix.stype = SIMPLE_STRU_INSTR;
  111. ix.share_id[0] = cpu_to_le32(ip->share_id[0]);
  112. ix.share_id[1] = cpu_to_le32(ip->share_id[1]);
  113. ix.share_id[2] = cpu_to_le32(ip->share_id[2]);
  114. ix.share_id[3] = cpu_to_le32(ip->share_id[3]);
  115. ix.format = cpu_to_le32(ip->format);
  116. ix.size = cpu_to_le32(ip->size);
  117. ix.start = cpu_to_le32(ip->start);
  118. ix.loop_start = cpu_to_le32(ip->loop_start);
  119. ix.loop_end = cpu_to_le32(ip->loop_end);
  120. ix.loop_repeat = cpu_to_le32(ip->loop_repeat);
  121. ix.effect1 = cpu_to_le16(ip->effect1);
  122. ix.effect1_depth = cpu_to_le16(ip->effect1_depth);
  123. ix.effect2 = ip->effect2;
  124. ix.effect2_depth = ip->effect2_depth;
  125. if (copy_to_user(instr_data, &ix, sizeof(ix)))
  126. return -EFAULT;
  127. instr_data += sizeof(ix);
  128. len -= sizeof(ix);
  129. real_size = snd_seq_simple_size(ip->size, ip->format);
  130. if (len < (long)real_size)
  131. return -ENOMEM;
  132. if (ops->get_sample) {
  133. err = ops->get_sample(ops->private_data, ip,
  134. instr_data, real_size, atomic);
  135. if (err < 0)
  136. return err;
  137. }
  138. return 0;
  139. }
  140. static int snd_seq_simple_get_size(void *private_data, struct snd_seq_kinstr *instr,
  141. long *size)
  142. {
  143. struct simple_instrument *ip;
  144. ip = (struct simple_instrument *)KINSTR_DATA(instr);
  145. *size = sizeof(struct simple_xinstrument) + snd_seq_simple_size(ip->size, ip->format);
  146. return 0;
  147. }
  148. static int snd_seq_simple_remove(void *private_data,
  149. struct snd_seq_kinstr *instr,
  150. int atomic)
  151. {
  152. struct snd_simple_ops *ops = private_data;
  153. struct simple_instrument *ip;
  154. ip = (struct simple_instrument *)KINSTR_DATA(instr);
  155. snd_seq_simple_instr_free(ops, ip, atomic);
  156. return 0;
  157. }
  158. static void snd_seq_simple_notify(void *private_data,
  159. struct snd_seq_kinstr *instr,
  160. int what)
  161. {
  162. struct snd_simple_ops *ops = private_data;
  163. if (ops->notify)
  164. ops->notify(ops->private_data, instr, what);
  165. }
  166. int snd_seq_simple_init(struct snd_simple_ops *ops,
  167. void *private_data,
  168. struct snd_seq_kinstr_ops *next)
  169. {
  170. memset(ops, 0, sizeof(*ops));
  171. ops->private_data = private_data;
  172. ops->kops.private_data = ops;
  173. ops->kops.add_len = sizeof(struct simple_instrument);
  174. ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_SIMPLE;
  175. ops->kops.put = snd_seq_simple_put;
  176. ops->kops.get = snd_seq_simple_get;
  177. ops->kops.get_size = snd_seq_simple_get_size;
  178. ops->kops.remove = snd_seq_simple_remove;
  179. ops->kops.notify = snd_seq_simple_notify;
  180. ops->kops.next = next;
  181. return 0;
  182. }
  183. /*
  184. * Init part
  185. */
  186. static int __init alsa_ainstr_simple_init(void)
  187. {
  188. return 0;
  189. }
  190. static void __exit alsa_ainstr_simple_exit(void)
  191. {
  192. }
  193. module_init(alsa_ainstr_simple_init)
  194. module_exit(alsa_ainstr_simple_exit)
  195. EXPORT_SYMBOL(snd_seq_simple_init);