ainstr_simple.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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/slab.h>
  23. #include <sound/core.h>
  24. #include <sound/ainstr_simple.h>
  25. #include <sound/initval.h>
  26. #include <asm/uaccess.h>
  27. MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
  28. MODULE_DESCRIPTION("Advanced Linux Sound Architecture Simple Instrument support.");
  29. MODULE_LICENSE("GPL");
  30. static unsigned int snd_seq_simple_size(unsigned int size, unsigned int format)
  31. {
  32. unsigned int result = size;
  33. if (format & SIMPLE_WAVE_16BIT)
  34. result <<= 1;
  35. if (format & SIMPLE_WAVE_STEREO)
  36. result <<= 1;
  37. return result;
  38. }
  39. static void snd_seq_simple_instr_free(struct snd_simple_ops *ops,
  40. struct simple_instrument *ip,
  41. int atomic)
  42. {
  43. if (ops->remove_sample)
  44. ops->remove_sample(ops->private_data, ip, atomic);
  45. }
  46. static int snd_seq_simple_put(void *private_data, struct snd_seq_kinstr *instr,
  47. char __user *instr_data, long len,
  48. int atomic, int cmd)
  49. {
  50. struct snd_simple_ops *ops = private_data;
  51. struct simple_instrument *ip;
  52. struct simple_xinstrument ix;
  53. int err;
  54. gfp_t gfp_mask;
  55. unsigned int real_size;
  56. if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
  57. return -EINVAL;
  58. gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
  59. /* copy instrument data */
  60. if (len < (long)sizeof(ix))
  61. return -EINVAL;
  62. if (copy_from_user(&ix, instr_data, sizeof(ix)))
  63. return -EFAULT;
  64. if (ix.stype != SIMPLE_STRU_INSTR)
  65. return -EINVAL;
  66. instr_data += sizeof(ix);
  67. len -= sizeof(ix);
  68. ip = (struct simple_instrument *)KINSTR_DATA(instr);
  69. ip->share_id[0] = le32_to_cpu(ix.share_id[0]);
  70. ip->share_id[1] = le32_to_cpu(ix.share_id[1]);
  71. ip->share_id[2] = le32_to_cpu(ix.share_id[2]);
  72. ip->share_id[3] = le32_to_cpu(ix.share_id[3]);
  73. ip->format = le32_to_cpu(ix.format);
  74. ip->size = le32_to_cpu(ix.size);
  75. ip->start = le32_to_cpu(ix.start);
  76. ip->loop_start = le32_to_cpu(ix.loop_start);
  77. ip->loop_end = le32_to_cpu(ix.loop_end);
  78. ip->loop_repeat = le16_to_cpu(ix.loop_repeat);
  79. ip->effect1 = ix.effect1;
  80. ip->effect1_depth = ix.effect1_depth;
  81. ip->effect2 = ix.effect2;
  82. ip->effect2_depth = ix.effect2_depth;
  83. real_size = snd_seq_simple_size(ip->size, ip->format);
  84. if (len < (long)real_size)
  85. return -EINVAL;
  86. if (ops->put_sample) {
  87. err = ops->put_sample(ops->private_data, ip,
  88. instr_data, real_size, atomic);
  89. if (err < 0)
  90. return err;
  91. }
  92. return 0;
  93. }
  94. static int snd_seq_simple_get(void *private_data, struct snd_seq_kinstr *instr,
  95. char __user *instr_data, long len,
  96. int atomic, int cmd)
  97. {
  98. struct snd_simple_ops *ops = private_data;
  99. struct simple_instrument *ip;
  100. struct simple_xinstrument ix;
  101. int err;
  102. unsigned int real_size;
  103. if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
  104. return -EINVAL;
  105. if (len < (long)sizeof(ix))
  106. return -ENOMEM;
  107. memset(&ix, 0, sizeof(ix));
  108. ip = (struct simple_instrument *)KINSTR_DATA(instr);
  109. ix.stype = SIMPLE_STRU_INSTR;
  110. ix.share_id[0] = cpu_to_le32(ip->share_id[0]);
  111. ix.share_id[1] = cpu_to_le32(ip->share_id[1]);
  112. ix.share_id[2] = cpu_to_le32(ip->share_id[2]);
  113. ix.share_id[3] = cpu_to_le32(ip->share_id[3]);
  114. ix.format = cpu_to_le32(ip->format);
  115. ix.size = cpu_to_le32(ip->size);
  116. ix.start = cpu_to_le32(ip->start);
  117. ix.loop_start = cpu_to_le32(ip->loop_start);
  118. ix.loop_end = cpu_to_le32(ip->loop_end);
  119. ix.loop_repeat = cpu_to_le32(ip->loop_repeat);
  120. ix.effect1 = cpu_to_le16(ip->effect1);
  121. ix.effect1_depth = cpu_to_le16(ip->effect1_depth);
  122. ix.effect2 = ip->effect2;
  123. ix.effect2_depth = ip->effect2_depth;
  124. if (copy_to_user(instr_data, &ix, sizeof(ix)))
  125. return -EFAULT;
  126. instr_data += sizeof(ix);
  127. len -= sizeof(ix);
  128. real_size = snd_seq_simple_size(ip->size, ip->format);
  129. if (len < (long)real_size)
  130. return -ENOMEM;
  131. if (ops->get_sample) {
  132. err = ops->get_sample(ops->private_data, ip,
  133. instr_data, real_size, atomic);
  134. if (err < 0)
  135. return err;
  136. }
  137. return 0;
  138. }
  139. static int snd_seq_simple_get_size(void *private_data, struct snd_seq_kinstr *instr,
  140. long *size)
  141. {
  142. struct simple_instrument *ip;
  143. ip = (struct simple_instrument *)KINSTR_DATA(instr);
  144. *size = sizeof(struct simple_xinstrument) + snd_seq_simple_size(ip->size, ip->format);
  145. return 0;
  146. }
  147. static int snd_seq_simple_remove(void *private_data,
  148. struct snd_seq_kinstr *instr,
  149. int atomic)
  150. {
  151. struct snd_simple_ops *ops = private_data;
  152. struct simple_instrument *ip;
  153. ip = (struct simple_instrument *)KINSTR_DATA(instr);
  154. snd_seq_simple_instr_free(ops, ip, atomic);
  155. return 0;
  156. }
  157. static void snd_seq_simple_notify(void *private_data,
  158. struct snd_seq_kinstr *instr,
  159. int what)
  160. {
  161. struct snd_simple_ops *ops = private_data;
  162. if (ops->notify)
  163. ops->notify(ops->private_data, instr, what);
  164. }
  165. int snd_seq_simple_init(struct snd_simple_ops *ops,
  166. void *private_data,
  167. struct snd_seq_kinstr_ops *next)
  168. {
  169. memset(ops, 0, sizeof(*ops));
  170. ops->private_data = private_data;
  171. ops->kops.private_data = ops;
  172. ops->kops.add_len = sizeof(struct simple_instrument);
  173. ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_SIMPLE;
  174. ops->kops.put = snd_seq_simple_put;
  175. ops->kops.get = snd_seq_simple_get;
  176. ops->kops.get_size = snd_seq_simple_get_size;
  177. ops->kops.remove = snd_seq_simple_remove;
  178. ops->kops.notify = snd_seq_simple_notify;
  179. ops->kops.next = next;
  180. return 0;
  181. }
  182. /*
  183. * Init part
  184. */
  185. static int __init alsa_ainstr_simple_init(void)
  186. {
  187. return 0;
  188. }
  189. static void __exit alsa_ainstr_simple_exit(void)
  190. {
  191. }
  192. module_init(alsa_ainstr_simple_init)
  193. module_exit(alsa_ainstr_simple_exit)
  194. EXPORT_SYMBOL(snd_seq_simple_init);