ainstr_iw.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. /*
  2. * IWFFFF - AMD InterWave (tm) - Instrument routines
  3. * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.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_iw.h>
  25. #include <sound/initval.h>
  26. #include <asm/uaccess.h>
  27. MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
  28. MODULE_DESCRIPTION("Advanced Linux Sound Architecture IWFFFF support.");
  29. MODULE_LICENSE("GPL");
  30. static unsigned int snd_seq_iwffff_size(unsigned int size, unsigned int format)
  31. {
  32. unsigned int result = size;
  33. if (format & IWFFFF_WAVE_16BIT)
  34. result <<= 1;
  35. if (format & IWFFFF_WAVE_STEREO)
  36. result <<= 1;
  37. return result;
  38. }
  39. static void snd_seq_iwffff_copy_lfo_from_stream(struct iwffff_lfo *fp,
  40. struct iwffff_xlfo *fx)
  41. {
  42. fp->freq = le16_to_cpu(fx->freq);
  43. fp->depth = le16_to_cpu(fx->depth);
  44. fp->sweep = le16_to_cpu(fx->sweep);
  45. fp->shape = fx->shape;
  46. fp->delay = fx->delay;
  47. }
  48. static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype,
  49. struct iwffff_layer *lp,
  50. struct iwffff_env *ep,
  51. struct iwffff_xenv *ex,
  52. char __user **data,
  53. long *len,
  54. gfp_t gfp_mask)
  55. {
  56. __u32 stype;
  57. struct iwffff_env_record *rp, *rp_last;
  58. struct iwffff_xenv_record rx;
  59. struct iwffff_env_point *pp;
  60. struct iwffff_xenv_point px;
  61. int points_size, idx;
  62. ep->flags = ex->flags;
  63. ep->mode = ex->mode;
  64. ep->index = ex->index;
  65. rp_last = NULL;
  66. while (1) {
  67. if (*len < (long)sizeof(__u32))
  68. return -EINVAL;
  69. if (copy_from_user(&stype, *data, sizeof(stype)))
  70. return -EFAULT;
  71. if (stype == IWFFFF_STRU_WAVE)
  72. return 0;
  73. if (req_stype != stype) {
  74. if (stype == IWFFFF_STRU_ENV_RECP ||
  75. stype == IWFFFF_STRU_ENV_RECV)
  76. return 0;
  77. }
  78. if (*len < (long)sizeof(rx))
  79. return -EINVAL;
  80. if (copy_from_user(&rx, *data, sizeof(rx)))
  81. return -EFAULT;
  82. *data += sizeof(rx);
  83. *len -= sizeof(rx);
  84. points_size = (le16_to_cpu(rx.nattack) + le16_to_cpu(rx.nrelease)) * 2 * sizeof(__u16);
  85. if (points_size > *len)
  86. return -EINVAL;
  87. rp = kzalloc(sizeof(*rp) + points_size, gfp_mask);
  88. if (rp == NULL)
  89. return -ENOMEM;
  90. rp->nattack = le16_to_cpu(rx.nattack);
  91. rp->nrelease = le16_to_cpu(rx.nrelease);
  92. rp->sustain_offset = le16_to_cpu(rx.sustain_offset);
  93. rp->sustain_rate = le16_to_cpu(rx.sustain_rate);
  94. rp->release_rate = le16_to_cpu(rx.release_rate);
  95. rp->hirange = rx.hirange;
  96. pp = (struct iwffff_env_point *)(rp + 1);
  97. for (idx = 0; idx < rp->nattack + rp->nrelease; idx++) {
  98. if (copy_from_user(&px, *data, sizeof(px)))
  99. return -EFAULT;
  100. *data += sizeof(px);
  101. *len -= sizeof(px);
  102. pp->offset = le16_to_cpu(px.offset);
  103. pp->rate = le16_to_cpu(px.rate);
  104. }
  105. if (ep->record == NULL) {
  106. ep->record = rp;
  107. } else {
  108. rp_last = rp;
  109. }
  110. rp_last = rp;
  111. }
  112. return 0;
  113. }
  114. static int snd_seq_iwffff_copy_wave_from_stream(struct snd_iwffff_ops *ops,
  115. struct iwffff_layer *lp,
  116. char __user **data,
  117. long *len,
  118. int atomic)
  119. {
  120. struct iwffff_wave *wp, *prev;
  121. struct iwffff_xwave xp;
  122. int err;
  123. gfp_t gfp_mask;
  124. unsigned int real_size;
  125. gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
  126. if (*len < (long)sizeof(xp))
  127. return -EINVAL;
  128. if (copy_from_user(&xp, *data, sizeof(xp)))
  129. return -EFAULT;
  130. *data += sizeof(xp);
  131. *len -= sizeof(xp);
  132. wp = kzalloc(sizeof(*wp), gfp_mask);
  133. if (wp == NULL)
  134. return -ENOMEM;
  135. wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
  136. wp->share_id[1] = le32_to_cpu(xp.share_id[1]);
  137. wp->share_id[2] = le32_to_cpu(xp.share_id[2]);
  138. wp->share_id[3] = le32_to_cpu(xp.share_id[3]);
  139. wp->format = le32_to_cpu(xp.format);
  140. wp->address.memory = le32_to_cpu(xp.offset);
  141. wp->size = le32_to_cpu(xp.size);
  142. wp->start = le32_to_cpu(xp.start);
  143. wp->loop_start = le32_to_cpu(xp.loop_start);
  144. wp->loop_end = le32_to_cpu(xp.loop_end);
  145. wp->loop_repeat = le16_to_cpu(xp.loop_repeat);
  146. wp->sample_ratio = le32_to_cpu(xp.sample_ratio);
  147. wp->attenuation = xp.attenuation;
  148. wp->low_note = xp.low_note;
  149. wp->high_note = xp.high_note;
  150. real_size = snd_seq_iwffff_size(wp->size, wp->format);
  151. if (!(wp->format & IWFFFF_WAVE_ROM)) {
  152. if ((long)real_size > *len) {
  153. kfree(wp);
  154. return -ENOMEM;
  155. }
  156. }
  157. if (ops->put_sample) {
  158. err = ops->put_sample(ops->private_data, wp,
  159. *data, real_size, atomic);
  160. if (err < 0) {
  161. kfree(wp);
  162. return err;
  163. }
  164. }
  165. if (!(wp->format & IWFFFF_WAVE_ROM)) {
  166. *data += real_size;
  167. *len -= real_size;
  168. }
  169. prev = lp->wave;
  170. if (prev) {
  171. while (prev->next) prev = prev->next;
  172. prev->next = wp;
  173. } else {
  174. lp->wave = wp;
  175. }
  176. return 0;
  177. }
  178. static void snd_seq_iwffff_env_free(struct snd_iwffff_ops *ops,
  179. struct iwffff_env *env,
  180. int atomic)
  181. {
  182. struct iwffff_env_record *rec;
  183. while ((rec = env->record) != NULL) {
  184. env->record = rec->next;
  185. kfree(rec);
  186. }
  187. }
  188. static void snd_seq_iwffff_wave_free(struct snd_iwffff_ops *ops,
  189. struct iwffff_wave *wave,
  190. int atomic)
  191. {
  192. if (ops->remove_sample)
  193. ops->remove_sample(ops->private_data, wave, atomic);
  194. kfree(wave);
  195. }
  196. static void snd_seq_iwffff_instr_free(struct snd_iwffff_ops *ops,
  197. struct iwffff_instrument *ip,
  198. int atomic)
  199. {
  200. struct iwffff_layer *layer;
  201. struct iwffff_wave *wave;
  202. while ((layer = ip->layer) != NULL) {
  203. ip->layer = layer->next;
  204. snd_seq_iwffff_env_free(ops, &layer->penv, atomic);
  205. snd_seq_iwffff_env_free(ops, &layer->venv, atomic);
  206. while ((wave = layer->wave) != NULL) {
  207. layer->wave = wave->next;
  208. snd_seq_iwffff_wave_free(ops, wave, atomic);
  209. }
  210. kfree(layer);
  211. }
  212. }
  213. static int snd_seq_iwffff_put(void *private_data, struct snd_seq_kinstr *instr,
  214. char __user *instr_data, long len, int atomic,
  215. int cmd)
  216. {
  217. struct snd_iwffff_ops *ops = private_data;
  218. struct iwffff_instrument *ip;
  219. struct iwffff_xinstrument ix;
  220. struct iwffff_layer *lp, *prev_lp;
  221. struct iwffff_xlayer lx;
  222. int err;
  223. gfp_t gfp_mask;
  224. if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
  225. return -EINVAL;
  226. gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
  227. /* copy instrument data */
  228. if (len < (long)sizeof(ix))
  229. return -EINVAL;
  230. if (copy_from_user(&ix, instr_data, sizeof(ix)))
  231. return -EFAULT;
  232. if (ix.stype != IWFFFF_STRU_INSTR)
  233. return -EINVAL;
  234. instr_data += sizeof(ix);
  235. len -= sizeof(ix);
  236. ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
  237. ip->exclusion = le16_to_cpu(ix.exclusion);
  238. ip->layer_type = le16_to_cpu(ix.layer_type);
  239. ip->exclusion_group = le16_to_cpu(ix.exclusion_group);
  240. ip->effect1 = ix.effect1;
  241. ip->effect1_depth = ix.effect1_depth;
  242. ip->effect2 = ix.effect2;
  243. ip->effect2_depth = ix.effect2_depth;
  244. /* copy layers */
  245. prev_lp = NULL;
  246. while (len > 0) {
  247. if (len < (long)sizeof(struct iwffff_xlayer)) {
  248. snd_seq_iwffff_instr_free(ops, ip, atomic);
  249. return -EINVAL;
  250. }
  251. if (copy_from_user(&lx, instr_data, sizeof(lx)))
  252. return -EFAULT;
  253. instr_data += sizeof(lx);
  254. len -= sizeof(lx);
  255. if (lx.stype != IWFFFF_STRU_LAYER) {
  256. snd_seq_iwffff_instr_free(ops, ip, atomic);
  257. return -EINVAL;
  258. }
  259. lp = kzalloc(sizeof(*lp), gfp_mask);
  260. if (lp == NULL) {
  261. snd_seq_iwffff_instr_free(ops, ip, atomic);
  262. return -ENOMEM;
  263. }
  264. if (prev_lp) {
  265. prev_lp->next = lp;
  266. } else {
  267. ip->layer = lp;
  268. }
  269. prev_lp = lp;
  270. lp->flags = lx.flags;
  271. lp->velocity_mode = lx.velocity_mode;
  272. lp->layer_event = lx.layer_event;
  273. lp->low_range = lx.low_range;
  274. lp->high_range = lx.high_range;
  275. lp->pan = lx.pan;
  276. lp->pan_freq_scale = lx.pan_freq_scale;
  277. lp->attenuation = lx.attenuation;
  278. snd_seq_iwffff_copy_lfo_from_stream(&lp->tremolo, &lx.tremolo);
  279. snd_seq_iwffff_copy_lfo_from_stream(&lp->vibrato, &lx.vibrato);
  280. lp->freq_scale = le16_to_cpu(lx.freq_scale);
  281. lp->freq_center = lx.freq_center;
  282. err = snd_seq_iwffff_copy_env_from_stream(IWFFFF_STRU_ENV_RECP,
  283. lp,
  284. &lp->penv, &lx.penv,
  285. &instr_data, &len,
  286. gfp_mask);
  287. if (err < 0) {
  288. snd_seq_iwffff_instr_free(ops, ip, atomic);
  289. return err;
  290. }
  291. err = snd_seq_iwffff_copy_env_from_stream(IWFFFF_STRU_ENV_RECV,
  292. lp,
  293. &lp->venv, &lx.venv,
  294. &instr_data, &len,
  295. gfp_mask);
  296. if (err < 0) {
  297. snd_seq_iwffff_instr_free(ops, ip, atomic);
  298. return err;
  299. }
  300. while (len > (long)sizeof(__u32)) {
  301. __u32 stype;
  302. if (copy_from_user(&stype, instr_data, sizeof(stype)))
  303. return -EFAULT;
  304. if (stype != IWFFFF_STRU_WAVE)
  305. break;
  306. err = snd_seq_iwffff_copy_wave_from_stream(ops,
  307. lp,
  308. &instr_data,
  309. &len,
  310. atomic);
  311. if (err < 0) {
  312. snd_seq_iwffff_instr_free(ops, ip, atomic);
  313. return err;
  314. }
  315. }
  316. }
  317. return 0;
  318. }
  319. static void snd_seq_iwffff_copy_lfo_to_stream(struct iwffff_xlfo *fx,
  320. struct iwffff_lfo *fp)
  321. {
  322. fx->freq = cpu_to_le16(fp->freq);
  323. fx->depth = cpu_to_le16(fp->depth);
  324. fx->sweep = cpu_to_le16(fp->sweep);
  325. fp->shape = fx->shape;
  326. fp->delay = fx->delay;
  327. }
  328. static int snd_seq_iwffff_copy_env_to_stream(__u32 req_stype,
  329. struct iwffff_layer *lp,
  330. struct iwffff_xenv *ex,
  331. struct iwffff_env *ep,
  332. char __user **data,
  333. long *len)
  334. {
  335. struct iwffff_env_record *rp;
  336. struct iwffff_xenv_record rx;
  337. struct iwffff_env_point *pp;
  338. struct iwffff_xenv_point px;
  339. int points_size, idx;
  340. ex->flags = ep->flags;
  341. ex->mode = ep->mode;
  342. ex->index = ep->index;
  343. for (rp = ep->record; rp; rp = rp->next) {
  344. if (*len < (long)sizeof(rx))
  345. return -ENOMEM;
  346. memset(&rx, 0, sizeof(rx));
  347. rx.stype = req_stype;
  348. rx.nattack = cpu_to_le16(rp->nattack);
  349. rx.nrelease = cpu_to_le16(rp->nrelease);
  350. rx.sustain_offset = cpu_to_le16(rp->sustain_offset);
  351. rx.sustain_rate = cpu_to_le16(rp->sustain_rate);
  352. rx.release_rate = cpu_to_le16(rp->release_rate);
  353. rx.hirange = cpu_to_le16(rp->hirange);
  354. if (copy_to_user(*data, &rx, sizeof(rx)))
  355. return -EFAULT;
  356. *data += sizeof(rx);
  357. *len -= sizeof(rx);
  358. points_size = (rp->nattack + rp->nrelease) * 2 * sizeof(__u16);
  359. if (*len < points_size)
  360. return -ENOMEM;
  361. pp = (struct iwffff_env_point *)(rp + 1);
  362. for (idx = 0; idx < rp->nattack + rp->nrelease; idx++) {
  363. px.offset = cpu_to_le16(pp->offset);
  364. px.rate = cpu_to_le16(pp->rate);
  365. if (copy_to_user(*data, &px, sizeof(px)))
  366. return -EFAULT;
  367. *data += sizeof(px);
  368. *len -= sizeof(px);
  369. }
  370. }
  371. return 0;
  372. }
  373. static int snd_seq_iwffff_copy_wave_to_stream(struct snd_iwffff_ops *ops,
  374. struct iwffff_layer *lp,
  375. char __user **data,
  376. long *len,
  377. int atomic)
  378. {
  379. struct iwffff_wave *wp;
  380. struct iwffff_xwave xp;
  381. int err;
  382. unsigned int real_size;
  383. for (wp = lp->wave; wp; wp = wp->next) {
  384. if (*len < (long)sizeof(xp))
  385. return -ENOMEM;
  386. memset(&xp, 0, sizeof(xp));
  387. xp.stype = IWFFFF_STRU_WAVE;
  388. xp.share_id[0] = cpu_to_le32(wp->share_id[0]);
  389. xp.share_id[1] = cpu_to_le32(wp->share_id[1]);
  390. xp.share_id[2] = cpu_to_le32(wp->share_id[2]);
  391. xp.share_id[3] = cpu_to_le32(wp->share_id[3]);
  392. xp.format = cpu_to_le32(wp->format);
  393. if (wp->format & IWFFFF_WAVE_ROM)
  394. xp.offset = cpu_to_le32(wp->address.memory);
  395. xp.size = cpu_to_le32(wp->size);
  396. xp.start = cpu_to_le32(wp->start);
  397. xp.loop_start = cpu_to_le32(wp->loop_start);
  398. xp.loop_end = cpu_to_le32(wp->loop_end);
  399. xp.loop_repeat = cpu_to_le32(wp->loop_repeat);
  400. xp.sample_ratio = cpu_to_le32(wp->sample_ratio);
  401. xp.attenuation = wp->attenuation;
  402. xp.low_note = wp->low_note;
  403. xp.high_note = wp->high_note;
  404. if (copy_to_user(*data, &xp, sizeof(xp)))
  405. return -EFAULT;
  406. *data += sizeof(xp);
  407. *len -= sizeof(xp);
  408. real_size = snd_seq_iwffff_size(wp->size, wp->format);
  409. if (!(wp->format & IWFFFF_WAVE_ROM)) {
  410. if (*len < (long)real_size)
  411. return -ENOMEM;
  412. }
  413. if (ops->get_sample) {
  414. err = ops->get_sample(ops->private_data, wp,
  415. *data, real_size, atomic);
  416. if (err < 0)
  417. return err;
  418. }
  419. if (!(wp->format & IWFFFF_WAVE_ROM)) {
  420. *data += real_size;
  421. *len -= real_size;
  422. }
  423. }
  424. return 0;
  425. }
  426. static int snd_seq_iwffff_get(void *private_data, struct snd_seq_kinstr *instr,
  427. char __user *instr_data, long len, int atomic, int cmd)
  428. {
  429. struct snd_iwffff_ops *ops = private_data;
  430. struct iwffff_instrument *ip;
  431. struct iwffff_xinstrument ix;
  432. struct iwffff_layer *lp;
  433. struct iwffff_xlayer lx;
  434. char __user *layer_instr_data;
  435. int err;
  436. if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
  437. return -EINVAL;
  438. if (len < (long)sizeof(ix))
  439. return -ENOMEM;
  440. memset(&ix, 0, sizeof(ix));
  441. ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
  442. ix.stype = IWFFFF_STRU_INSTR;
  443. ix.exclusion = cpu_to_le16(ip->exclusion);
  444. ix.layer_type = cpu_to_le16(ip->layer_type);
  445. ix.exclusion_group = cpu_to_le16(ip->exclusion_group);
  446. ix.effect1 = cpu_to_le16(ip->effect1);
  447. ix.effect1_depth = cpu_to_le16(ip->effect1_depth);
  448. ix.effect2 = ip->effect2;
  449. ix.effect2_depth = ip->effect2_depth;
  450. if (copy_to_user(instr_data, &ix, sizeof(ix)))
  451. return -EFAULT;
  452. instr_data += sizeof(ix);
  453. len -= sizeof(ix);
  454. for (lp = ip->layer; lp; lp = lp->next) {
  455. if (len < (long)sizeof(lx))
  456. return -ENOMEM;
  457. memset(&lx, 0, sizeof(lx));
  458. lx.stype = IWFFFF_STRU_LAYER;
  459. lx.flags = lp->flags;
  460. lx.velocity_mode = lp->velocity_mode;
  461. lx.layer_event = lp->layer_event;
  462. lx.low_range = lp->low_range;
  463. lx.high_range = lp->high_range;
  464. lx.pan = lp->pan;
  465. lx.pan_freq_scale = lp->pan_freq_scale;
  466. lx.attenuation = lp->attenuation;
  467. snd_seq_iwffff_copy_lfo_to_stream(&lx.tremolo, &lp->tremolo);
  468. snd_seq_iwffff_copy_lfo_to_stream(&lx.vibrato, &lp->vibrato);
  469. layer_instr_data = instr_data;
  470. instr_data += sizeof(lx);
  471. len -= sizeof(lx);
  472. err = snd_seq_iwffff_copy_env_to_stream(IWFFFF_STRU_ENV_RECP,
  473. lp,
  474. &lx.penv, &lp->penv,
  475. &instr_data, &len);
  476. if (err < 0)
  477. return err;
  478. err = snd_seq_iwffff_copy_env_to_stream(IWFFFF_STRU_ENV_RECV,
  479. lp,
  480. &lx.venv, &lp->venv,
  481. &instr_data, &len);
  482. if (err < 0)
  483. return err;
  484. /* layer structure updating is now finished */
  485. if (copy_to_user(layer_instr_data, &lx, sizeof(lx)))
  486. return -EFAULT;
  487. err = snd_seq_iwffff_copy_wave_to_stream(ops,
  488. lp,
  489. &instr_data,
  490. &len,
  491. atomic);
  492. if (err < 0)
  493. return err;
  494. }
  495. return 0;
  496. }
  497. static long snd_seq_iwffff_env_size_in_stream(struct iwffff_env *ep)
  498. {
  499. long result = 0;
  500. struct iwffff_env_record *rp;
  501. for (rp = ep->record; rp; rp = rp->next) {
  502. result += sizeof(struct iwffff_xenv_record);
  503. result += (rp->nattack + rp->nrelease) * 2 * sizeof(__u16);
  504. }
  505. return 0;
  506. }
  507. static long snd_seq_iwffff_wave_size_in_stream(struct iwffff_layer *lp)
  508. {
  509. long result = 0;
  510. struct iwffff_wave *wp;
  511. for (wp = lp->wave; wp; wp = wp->next) {
  512. result += sizeof(struct iwffff_xwave);
  513. if (!(wp->format & IWFFFF_WAVE_ROM))
  514. result += wp->size;
  515. }
  516. return result;
  517. }
  518. static int snd_seq_iwffff_get_size(void *private_data, struct snd_seq_kinstr *instr,
  519. long *size)
  520. {
  521. long result;
  522. struct iwffff_instrument *ip;
  523. struct iwffff_layer *lp;
  524. *size = 0;
  525. ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
  526. result = sizeof(struct iwffff_xinstrument);
  527. for (lp = ip->layer; lp; lp = lp->next) {
  528. result += sizeof(struct iwffff_xlayer);
  529. result += snd_seq_iwffff_env_size_in_stream(&lp->penv);
  530. result += snd_seq_iwffff_env_size_in_stream(&lp->venv);
  531. result += snd_seq_iwffff_wave_size_in_stream(lp);
  532. }
  533. *size = result;
  534. return 0;
  535. }
  536. static int snd_seq_iwffff_remove(void *private_data,
  537. struct snd_seq_kinstr *instr,
  538. int atomic)
  539. {
  540. struct snd_iwffff_ops *ops = private_data;
  541. struct iwffff_instrument *ip;
  542. ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
  543. snd_seq_iwffff_instr_free(ops, ip, atomic);
  544. return 0;
  545. }
  546. static void snd_seq_iwffff_notify(void *private_data,
  547. struct snd_seq_kinstr *instr,
  548. int what)
  549. {
  550. struct snd_iwffff_ops *ops = private_data;
  551. if (ops->notify)
  552. ops->notify(ops->private_data, instr, what);
  553. }
  554. int snd_seq_iwffff_init(struct snd_iwffff_ops *ops,
  555. void *private_data,
  556. struct snd_seq_kinstr_ops *next)
  557. {
  558. memset(ops, 0, sizeof(*ops));
  559. ops->private_data = private_data;
  560. ops->kops.private_data = ops;
  561. ops->kops.add_len = sizeof(struct iwffff_instrument);
  562. ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_INTERWAVE;
  563. ops->kops.put = snd_seq_iwffff_put;
  564. ops->kops.get = snd_seq_iwffff_get;
  565. ops->kops.get_size = snd_seq_iwffff_get_size;
  566. ops->kops.remove = snd_seq_iwffff_remove;
  567. ops->kops.notify = snd_seq_iwffff_notify;
  568. ops->kops.next = next;
  569. return 0;
  570. }
  571. /*
  572. * Init part
  573. */
  574. static int __init alsa_ainstr_iw_init(void)
  575. {
  576. return 0;
  577. }
  578. static void __exit alsa_ainstr_iw_exit(void)
  579. {
  580. }
  581. module_init(alsa_ainstr_iw_init)
  582. module_exit(alsa_ainstr_iw_exit)
  583. EXPORT_SYMBOL(snd_seq_iwffff_init);