ainstr_iw.c 17 KB

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