info.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Information interface for ALSA driver
  4. * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
  5. */
  6. #include <linux/init.h>
  7. #include <linux/time.h>
  8. #include <linux/mm.h>
  9. #include <linux/slab.h>
  10. #include <linux/string.h>
  11. #include <linux/module.h>
  12. #include <sound/core.h>
  13. #include <sound/minors.h>
  14. #include <sound/info.h>
  15. #include <linux/utsname.h>
  16. #include <linux/proc_fs.h>
  17. #include <linux/mutex.h>
  18. int snd_info_check_reserved_words(const char *str)
  19. {
  20. static const char * const reserved[] =
  21. {
  22. "version",
  23. "meminfo",
  24. "memdebug",
  25. "detect",
  26. "devices",
  27. "oss",
  28. "cards",
  29. "timers",
  30. "synth",
  31. "pcm",
  32. "seq",
  33. NULL
  34. };
  35. const char * const *xstr = reserved;
  36. while (*xstr) {
  37. if (!strcmp(*xstr, str))
  38. return 0;
  39. xstr++;
  40. }
  41. if (!strncmp(str, "card", 4))
  42. return 0;
  43. return 1;
  44. }
  45. static DEFINE_MUTEX(info_mutex);
  46. struct snd_info_private_data {
  47. struct snd_info_buffer *rbuffer;
  48. struct snd_info_buffer *wbuffer;
  49. struct snd_info_entry *entry;
  50. void *file_private_data;
  51. };
  52. static int snd_info_version_init(void);
  53. static void snd_info_clear_entries(struct snd_info_entry *entry);
  54. /*
  55. */
  56. static struct snd_info_entry *snd_proc_root;
  57. struct snd_info_entry *snd_seq_root;
  58. EXPORT_SYMBOL(snd_seq_root);
  59. #ifdef CONFIG_SND_OSSEMUL
  60. struct snd_info_entry *snd_oss_root;
  61. #endif
  62. static int alloc_info_private(struct snd_info_entry *entry,
  63. struct snd_info_private_data **ret)
  64. {
  65. struct snd_info_private_data *data;
  66. if (!entry || !entry->p)
  67. return -ENODEV;
  68. if (!try_module_get(entry->module))
  69. return -EFAULT;
  70. data = kzalloc(sizeof(*data), GFP_KERNEL);
  71. if (!data) {
  72. module_put(entry->module);
  73. return -ENOMEM;
  74. }
  75. data->entry = entry;
  76. *ret = data;
  77. return 0;
  78. }
  79. static bool valid_pos(loff_t pos, size_t count)
  80. {
  81. if (pos < 0 || (long) pos != pos || (ssize_t) count < 0)
  82. return false;
  83. if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos)
  84. return false;
  85. return true;
  86. }
  87. /*
  88. * file ops for binary proc files
  89. */
  90. static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
  91. {
  92. struct snd_info_private_data *data;
  93. struct snd_info_entry *entry;
  94. loff_t size;
  95. data = file->private_data;
  96. entry = data->entry;
  97. guard(mutex)(&entry->access);
  98. if (entry->c.ops->llseek)
  99. return entry->c.ops->llseek(entry,
  100. data->file_private_data,
  101. file, offset, orig);
  102. size = entry->size;
  103. switch (orig) {
  104. case SEEK_SET:
  105. break;
  106. case SEEK_CUR:
  107. offset += file->f_pos;
  108. break;
  109. case SEEK_END:
  110. if (!size)
  111. return -EINVAL;
  112. offset += size;
  113. break;
  114. default:
  115. return -EINVAL;
  116. }
  117. if (offset < 0)
  118. return -EINVAL;
  119. if (size && offset > size)
  120. offset = size;
  121. file->f_pos = offset;
  122. return offset;
  123. }
  124. static ssize_t snd_info_entry_read(struct file *file, char __user *buffer,
  125. size_t count, loff_t * offset)
  126. {
  127. struct snd_info_private_data *data = file->private_data;
  128. struct snd_info_entry *entry = data->entry;
  129. size_t size;
  130. loff_t pos;
  131. pos = *offset;
  132. if (!valid_pos(pos, count))
  133. return -EIO;
  134. if (pos >= entry->size)
  135. return 0;
  136. size = entry->size - pos;
  137. size = min(count, size);
  138. size = entry->c.ops->read(entry, data->file_private_data,
  139. file, buffer, size, pos);
  140. if ((ssize_t) size > 0)
  141. *offset = pos + size;
  142. return size;
  143. }
  144. static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer,
  145. size_t count, loff_t * offset)
  146. {
  147. struct snd_info_private_data *data = file->private_data;
  148. struct snd_info_entry *entry = data->entry;
  149. ssize_t size = 0;
  150. loff_t pos;
  151. pos = *offset;
  152. if (!valid_pos(pos, count))
  153. return -EIO;
  154. if (count > 0) {
  155. size_t maxsize = entry->size - pos;
  156. count = min(count, maxsize);
  157. size = entry->c.ops->write(entry, data->file_private_data,
  158. file, buffer, count, pos);
  159. }
  160. if (size > 0)
  161. *offset = pos + size;
  162. return size;
  163. }
  164. static __poll_t snd_info_entry_poll(struct file *file, poll_table *wait)
  165. {
  166. struct snd_info_private_data *data = file->private_data;
  167. struct snd_info_entry *entry = data->entry;
  168. __poll_t mask = 0;
  169. if (entry->c.ops->poll)
  170. return entry->c.ops->poll(entry,
  171. data->file_private_data,
  172. file, wait);
  173. if (entry->c.ops->read)
  174. mask |= EPOLLIN | EPOLLRDNORM;
  175. if (entry->c.ops->write)
  176. mask |= EPOLLOUT | EPOLLWRNORM;
  177. return mask;
  178. }
  179. static long snd_info_entry_ioctl(struct file *file, unsigned int cmd,
  180. unsigned long arg)
  181. {
  182. struct snd_info_private_data *data = file->private_data;
  183. struct snd_info_entry *entry = data->entry;
  184. if (!entry->c.ops->ioctl)
  185. return -ENOTTY;
  186. return entry->c.ops->ioctl(entry, data->file_private_data,
  187. file, cmd, arg);
  188. }
  189. static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
  190. {
  191. struct inode *inode = file_inode(file);
  192. struct snd_info_private_data *data;
  193. struct snd_info_entry *entry;
  194. data = file->private_data;
  195. if (data == NULL)
  196. return 0;
  197. entry = data->entry;
  198. if (!entry->c.ops->mmap)
  199. return -ENXIO;
  200. return entry->c.ops->mmap(entry, data->file_private_data,
  201. inode, file, vma);
  202. }
  203. static int snd_info_entry_open(struct inode *inode, struct file *file)
  204. {
  205. struct snd_info_entry *entry = pde_data(inode);
  206. struct snd_info_private_data *data;
  207. int mode, err;
  208. guard(mutex)(&info_mutex);
  209. err = alloc_info_private(entry, &data);
  210. if (err < 0)
  211. return err;
  212. mode = file->f_flags & O_ACCMODE;
  213. if (((mode == O_RDONLY || mode == O_RDWR) && !entry->c.ops->read) ||
  214. ((mode == O_WRONLY || mode == O_RDWR) && !entry->c.ops->write)) {
  215. err = -ENODEV;
  216. goto error;
  217. }
  218. if (entry->c.ops->open) {
  219. err = entry->c.ops->open(entry, mode, &data->file_private_data);
  220. if (err < 0)
  221. goto error;
  222. }
  223. file->private_data = data;
  224. return 0;
  225. error:
  226. kfree(data);
  227. module_put(entry->module);
  228. return err;
  229. }
  230. static int snd_info_entry_release(struct inode *inode, struct file *file)
  231. {
  232. struct snd_info_private_data *data = file->private_data;
  233. struct snd_info_entry *entry = data->entry;
  234. if (entry->c.ops->release)
  235. entry->c.ops->release(entry, file->f_flags & O_ACCMODE,
  236. data->file_private_data);
  237. module_put(entry->module);
  238. kfree(data);
  239. return 0;
  240. }
  241. static const struct proc_ops snd_info_entry_operations =
  242. {
  243. .proc_lseek = snd_info_entry_llseek,
  244. .proc_read = snd_info_entry_read,
  245. .proc_write = snd_info_entry_write,
  246. .proc_poll = snd_info_entry_poll,
  247. .proc_ioctl = snd_info_entry_ioctl,
  248. .proc_mmap = snd_info_entry_mmap,
  249. .proc_open = snd_info_entry_open,
  250. .proc_release = snd_info_entry_release,
  251. };
  252. /*
  253. * file ops for text proc files
  254. */
  255. static ssize_t snd_info_text_entry_write(struct file *file,
  256. const char __user *buffer,
  257. size_t count, loff_t *offset)
  258. {
  259. struct seq_file *m = file->private_data;
  260. struct snd_info_private_data *data = m->private;
  261. struct snd_info_entry *entry = data->entry;
  262. struct snd_info_buffer *buf;
  263. loff_t pos;
  264. size_t next;
  265. if (!entry->c.text.write)
  266. return -EIO;
  267. pos = *offset;
  268. if (!valid_pos(pos, count))
  269. return -EIO;
  270. next = pos + count;
  271. /* don't handle too large text inputs */
  272. if (next > 16 * 1024)
  273. return -EIO;
  274. guard(mutex)(&entry->access);
  275. buf = data->wbuffer;
  276. if (!buf) {
  277. data->wbuffer = buf = kzalloc(sizeof(*buf), GFP_KERNEL);
  278. if (!buf)
  279. return -ENOMEM;
  280. }
  281. if (next > buf->len) {
  282. char *nbuf = kvzalloc(PAGE_ALIGN(next), GFP_KERNEL);
  283. if (!nbuf)
  284. return -ENOMEM;
  285. kvfree(buf->buffer);
  286. buf->buffer = nbuf;
  287. buf->len = PAGE_ALIGN(next);
  288. }
  289. if (copy_from_user(buf->buffer + pos, buffer, count))
  290. return -EFAULT;
  291. buf->size = next;
  292. *offset = next;
  293. return count;
  294. }
  295. static int snd_info_seq_show(struct seq_file *seq, void *p)
  296. {
  297. struct snd_info_private_data *data = seq->private;
  298. struct snd_info_entry *entry = data->entry;
  299. if (!entry->c.text.read) {
  300. return -EIO;
  301. } else {
  302. data->rbuffer->buffer = (char *)seq; /* XXX hack! */
  303. entry->c.text.read(entry, data->rbuffer);
  304. }
  305. return 0;
  306. }
  307. static int snd_info_text_entry_open(struct inode *inode, struct file *file)
  308. {
  309. struct snd_info_entry *entry = pde_data(inode);
  310. struct snd_info_private_data *data;
  311. int err;
  312. guard(mutex)(&info_mutex);
  313. err = alloc_info_private(entry, &data);
  314. if (err < 0)
  315. return err;
  316. data->rbuffer = kzalloc(sizeof(*data->rbuffer), GFP_KERNEL);
  317. if (!data->rbuffer) {
  318. err = -ENOMEM;
  319. goto error;
  320. }
  321. if (entry->size)
  322. err = single_open_size(file, snd_info_seq_show, data,
  323. entry->size);
  324. else
  325. err = single_open(file, snd_info_seq_show, data);
  326. if (err < 0)
  327. goto error;
  328. return 0;
  329. error:
  330. kfree(data->rbuffer);
  331. kfree(data);
  332. module_put(entry->module);
  333. return err;
  334. }
  335. static int snd_info_text_entry_release(struct inode *inode, struct file *file)
  336. {
  337. struct seq_file *m = file->private_data;
  338. struct snd_info_private_data *data = m->private;
  339. struct snd_info_entry *entry = data->entry;
  340. if (data->wbuffer && entry->c.text.write)
  341. entry->c.text.write(entry, data->wbuffer);
  342. single_release(inode, file);
  343. kfree(data->rbuffer);
  344. if (data->wbuffer) {
  345. kvfree(data->wbuffer->buffer);
  346. kfree(data->wbuffer);
  347. }
  348. module_put(entry->module);
  349. kfree(data);
  350. return 0;
  351. }
  352. static const struct proc_ops snd_info_text_entry_ops =
  353. {
  354. .proc_open = snd_info_text_entry_open,
  355. .proc_release = snd_info_text_entry_release,
  356. .proc_write = snd_info_text_entry_write,
  357. .proc_lseek = seq_lseek,
  358. .proc_read = seq_read,
  359. };
  360. static struct snd_info_entry *create_subdir(struct module *mod,
  361. const char *name)
  362. {
  363. struct snd_info_entry *entry;
  364. entry = snd_info_create_module_entry(mod, name, NULL);
  365. if (!entry)
  366. return NULL;
  367. entry->mode = S_IFDIR | 0555;
  368. if (snd_info_register(entry) < 0) {
  369. snd_info_free_entry(entry);
  370. return NULL;
  371. }
  372. return entry;
  373. }
  374. static struct snd_info_entry *
  375. snd_info_create_entry(const char *name, struct snd_info_entry *parent,
  376. struct module *module);
  377. int __init snd_info_init(void)
  378. {
  379. snd_proc_root = snd_info_create_entry("asound", NULL, THIS_MODULE);
  380. if (!snd_proc_root)
  381. return -ENOMEM;
  382. snd_proc_root->mode = S_IFDIR | 0555;
  383. snd_proc_root->p = proc_mkdir("asound", NULL);
  384. if (!snd_proc_root->p)
  385. goto error;
  386. #ifdef CONFIG_SND_OSSEMUL
  387. snd_oss_root = create_subdir(THIS_MODULE, "oss");
  388. if (!snd_oss_root)
  389. goto error;
  390. #endif
  391. #if IS_ENABLED(CONFIG_SND_SEQUENCER)
  392. snd_seq_root = create_subdir(THIS_MODULE, "seq");
  393. if (!snd_seq_root)
  394. goto error;
  395. #endif
  396. if (snd_info_version_init() < 0 ||
  397. snd_minor_info_init() < 0 ||
  398. snd_minor_info_oss_init() < 0 ||
  399. snd_card_info_init() < 0 ||
  400. snd_info_minor_register() < 0)
  401. goto error;
  402. return 0;
  403. error:
  404. snd_info_free_entry(snd_proc_root);
  405. return -ENOMEM;
  406. }
  407. int __exit snd_info_done(void)
  408. {
  409. snd_info_free_entry(snd_proc_root);
  410. return 0;
  411. }
  412. static void snd_card_id_read(struct snd_info_entry *entry,
  413. struct snd_info_buffer *buffer)
  414. {
  415. struct snd_card *card = entry->private_data;
  416. snd_iprintf(buffer, "%s\n", card->id);
  417. }
  418. /*
  419. * create a card proc file
  420. * called from init.c
  421. */
  422. int snd_info_card_create(struct snd_card *card)
  423. {
  424. char str[8];
  425. struct snd_info_entry *entry;
  426. if (snd_BUG_ON(!card))
  427. return -ENXIO;
  428. sprintf(str, "card%i", card->number);
  429. entry = create_subdir(card->module, str);
  430. if (!entry)
  431. return -ENOMEM;
  432. card->proc_root = entry;
  433. return snd_card_ro_proc_new(card, "id", card, snd_card_id_read);
  434. }
  435. /*
  436. * register the card proc file
  437. * called from init.c
  438. * can be called multiple times for reinitialization
  439. */
  440. int snd_info_card_register(struct snd_card *card)
  441. {
  442. struct proc_dir_entry *p;
  443. int err;
  444. if (snd_BUG_ON(!card))
  445. return -ENXIO;
  446. err = snd_info_register(card->proc_root);
  447. if (err < 0)
  448. return err;
  449. if (!strcmp(card->id, card->proc_root->name))
  450. return 0;
  451. if (card->proc_root_link)
  452. return 0;
  453. p = proc_symlink(card->id, snd_proc_root->p, card->proc_root->name);
  454. if (!p)
  455. return -ENOMEM;
  456. card->proc_root_link = p;
  457. return 0;
  458. }
  459. /*
  460. * called on card->id change
  461. */
  462. void snd_info_card_id_change(struct snd_card *card)
  463. {
  464. guard(mutex)(&info_mutex);
  465. if (card->proc_root_link) {
  466. proc_remove(card->proc_root_link);
  467. card->proc_root_link = NULL;
  468. }
  469. if (strcmp(card->id, card->proc_root->name))
  470. card->proc_root_link = proc_symlink(card->id,
  471. snd_proc_root->p,
  472. card->proc_root->name);
  473. }
  474. /*
  475. * de-register the card proc file
  476. * called from init.c
  477. */
  478. void snd_info_card_disconnect(struct snd_card *card)
  479. {
  480. if (!card)
  481. return;
  482. proc_remove(card->proc_root_link);
  483. if (card->proc_root)
  484. proc_remove(card->proc_root->p);
  485. guard(mutex)(&info_mutex);
  486. if (card->proc_root)
  487. snd_info_clear_entries(card->proc_root);
  488. card->proc_root_link = NULL;
  489. card->proc_root = NULL;
  490. }
  491. /*
  492. * release the card proc file resources
  493. * called from init.c
  494. */
  495. int snd_info_card_free(struct snd_card *card)
  496. {
  497. if (!card)
  498. return 0;
  499. snd_info_free_entry(card->proc_root);
  500. card->proc_root = NULL;
  501. return 0;
  502. }
  503. /**
  504. * snd_info_get_line - read one line from the procfs buffer
  505. * @buffer: the procfs buffer
  506. * @line: the buffer to store
  507. * @len: the max. buffer size
  508. *
  509. * Reads one line from the buffer and stores the string.
  510. *
  511. * Return: Zero if successful, or 1 if error or EOF.
  512. */
  513. int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)
  514. {
  515. int c;
  516. if (snd_BUG_ON(!buffer))
  517. return 1;
  518. if (!buffer->buffer)
  519. return 1;
  520. if (len <= 0 || buffer->stop || buffer->error)
  521. return 1;
  522. while (!buffer->stop) {
  523. c = buffer->buffer[buffer->curr++];
  524. if (buffer->curr >= buffer->size)
  525. buffer->stop = 1;
  526. if (c == '\n')
  527. break;
  528. if (len > 1) {
  529. len--;
  530. *line++ = c;
  531. }
  532. }
  533. *line = '\0';
  534. return 0;
  535. }
  536. EXPORT_SYMBOL(snd_info_get_line);
  537. /**
  538. * snd_info_get_str - parse a string token
  539. * @dest: the buffer to store the string token
  540. * @src: the original string
  541. * @len: the max. length of token - 1
  542. *
  543. * Parses the original string and copy a token to the given
  544. * string buffer.
  545. *
  546. * Return: The updated pointer of the original string so that
  547. * it can be used for the next call.
  548. */
  549. const char *snd_info_get_str(char *dest, const char *src, int len)
  550. {
  551. int c;
  552. while (*src == ' ' || *src == '\t')
  553. src++;
  554. if (*src == '"' || *src == '\'') {
  555. c = *src++;
  556. while (--len > 0 && *src && *src != c) {
  557. *dest++ = *src++;
  558. }
  559. if (*src == c)
  560. src++;
  561. } else {
  562. while (--len > 0 && *src && *src != ' ' && *src != '\t') {
  563. *dest++ = *src++;
  564. }
  565. }
  566. *dest = 0;
  567. while (*src == ' ' || *src == '\t')
  568. src++;
  569. return src;
  570. }
  571. EXPORT_SYMBOL(snd_info_get_str);
  572. /*
  573. * snd_info_create_entry - create an info entry
  574. * @name: the proc file name
  575. * @parent: the parent directory
  576. *
  577. * Creates an info entry with the given file name and initializes as
  578. * the default state.
  579. *
  580. * Usually called from other functions such as
  581. * snd_info_create_card_entry().
  582. *
  583. * Return: The pointer of the new instance, or %NULL on failure.
  584. */
  585. static struct snd_info_entry *
  586. snd_info_create_entry(const char *name, struct snd_info_entry *parent,
  587. struct module *module)
  588. {
  589. struct snd_info_entry *entry;
  590. entry = kzalloc(sizeof(*entry), GFP_KERNEL);
  591. if (entry == NULL)
  592. return NULL;
  593. entry->name = kstrdup(name, GFP_KERNEL);
  594. if (entry->name == NULL) {
  595. kfree(entry);
  596. return NULL;
  597. }
  598. entry->mode = S_IFREG | 0444;
  599. entry->content = SNDRV_INFO_CONTENT_TEXT;
  600. mutex_init(&entry->access);
  601. INIT_LIST_HEAD(&entry->children);
  602. INIT_LIST_HEAD(&entry->list);
  603. entry->parent = parent;
  604. entry->module = module;
  605. if (parent) {
  606. guard(mutex)(&parent->access);
  607. list_add_tail(&entry->list, &parent->children);
  608. }
  609. return entry;
  610. }
  611. /**
  612. * snd_info_create_module_entry - create an info entry for the given module
  613. * @module: the module pointer
  614. * @name: the file name
  615. * @parent: the parent directory
  616. *
  617. * Creates a new info entry and assigns it to the given module.
  618. *
  619. * Return: The pointer of the new instance, or %NULL on failure.
  620. */
  621. struct snd_info_entry *snd_info_create_module_entry(struct module * module,
  622. const char *name,
  623. struct snd_info_entry *parent)
  624. {
  625. if (!parent)
  626. parent = snd_proc_root;
  627. return snd_info_create_entry(name, parent, module);
  628. }
  629. EXPORT_SYMBOL(snd_info_create_module_entry);
  630. /**
  631. * snd_info_create_card_entry - create an info entry for the given card
  632. * @card: the card instance
  633. * @name: the file name
  634. * @parent: the parent directory
  635. *
  636. * Creates a new info entry and assigns it to the given card.
  637. *
  638. * Return: The pointer of the new instance, or %NULL on failure.
  639. */
  640. struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
  641. const char *name,
  642. struct snd_info_entry * parent)
  643. {
  644. if (!parent)
  645. parent = card->proc_root;
  646. return snd_info_create_entry(name, parent, card->module);
  647. }
  648. EXPORT_SYMBOL(snd_info_create_card_entry);
  649. static void snd_info_clear_entries(struct snd_info_entry *entry)
  650. {
  651. struct snd_info_entry *p;
  652. if (!entry->p)
  653. return;
  654. list_for_each_entry(p, &entry->children, list)
  655. snd_info_clear_entries(p);
  656. entry->p = NULL;
  657. }
  658. /**
  659. * snd_info_free_entry - release the info entry
  660. * @entry: the info entry
  661. *
  662. * Releases the info entry.
  663. */
  664. void snd_info_free_entry(struct snd_info_entry * entry)
  665. {
  666. struct snd_info_entry *p, *n;
  667. if (!entry)
  668. return;
  669. if (entry->p) {
  670. proc_remove(entry->p);
  671. guard(mutex)(&info_mutex);
  672. snd_info_clear_entries(entry);
  673. }
  674. /* free all children at first */
  675. list_for_each_entry_safe(p, n, &entry->children, list)
  676. snd_info_free_entry(p);
  677. p = entry->parent;
  678. if (p) {
  679. guard(mutex)(&p->access);
  680. list_del(&entry->list);
  681. }
  682. kfree(entry->name);
  683. if (entry->private_free)
  684. entry->private_free(entry);
  685. kfree(entry);
  686. }
  687. EXPORT_SYMBOL(snd_info_free_entry);
  688. static int __snd_info_register(struct snd_info_entry *entry)
  689. {
  690. struct proc_dir_entry *root, *p = NULL;
  691. if (snd_BUG_ON(!entry))
  692. return -ENXIO;
  693. root = entry->parent == NULL ? snd_proc_root->p : entry->parent->p;
  694. guard(mutex)(&info_mutex);
  695. if (entry->p || !root)
  696. return 0;
  697. if (S_ISDIR(entry->mode)) {
  698. p = proc_mkdir_mode(entry->name, entry->mode, root);
  699. if (!p)
  700. return -ENOMEM;
  701. } else {
  702. const struct proc_ops *ops;
  703. if (entry->content == SNDRV_INFO_CONTENT_DATA)
  704. ops = &snd_info_entry_operations;
  705. else
  706. ops = &snd_info_text_entry_ops;
  707. p = proc_create_data(entry->name, entry->mode, root,
  708. ops, entry);
  709. if (!p)
  710. return -ENOMEM;
  711. proc_set_size(p, entry->size);
  712. }
  713. entry->p = p;
  714. return 0;
  715. }
  716. /**
  717. * snd_info_register - register the info entry
  718. * @entry: the info entry
  719. *
  720. * Registers the proc info entry.
  721. * The all children entries are registered recursively.
  722. *
  723. * Return: Zero if successful, or a negative error code on failure.
  724. */
  725. int snd_info_register(struct snd_info_entry *entry)
  726. {
  727. struct snd_info_entry *p;
  728. int err;
  729. if (!entry->p) {
  730. err = __snd_info_register(entry);
  731. if (err < 0)
  732. return err;
  733. }
  734. list_for_each_entry(p, &entry->children, list) {
  735. err = snd_info_register(p);
  736. if (err < 0)
  737. return err;
  738. }
  739. return 0;
  740. }
  741. EXPORT_SYMBOL(snd_info_register);
  742. /**
  743. * snd_card_rw_proc_new - Create a read/write text proc file entry for the card
  744. * @card: the card instance
  745. * @name: the file name
  746. * @private_data: the arbitrary private data
  747. * @read: the read callback
  748. * @write: the write callback, NULL for read-only
  749. *
  750. * This proc file entry will be registered via snd_card_register() call, and
  751. * it will be removed automatically at the card removal, too.
  752. *
  753. * Return: zero if successful, or a negative error code
  754. */
  755. int snd_card_rw_proc_new(struct snd_card *card, const char *name,
  756. void *private_data,
  757. void (*read)(struct snd_info_entry *,
  758. struct snd_info_buffer *),
  759. void (*write)(struct snd_info_entry *entry,
  760. struct snd_info_buffer *buffer))
  761. {
  762. struct snd_info_entry *entry;
  763. entry = snd_info_create_card_entry(card, name, card->proc_root);
  764. if (!entry)
  765. return -ENOMEM;
  766. snd_info_set_text_ops(entry, private_data, read);
  767. if (write) {
  768. entry->mode |= 0200;
  769. entry->c.text.write = write;
  770. }
  771. return 0;
  772. }
  773. EXPORT_SYMBOL_GPL(snd_card_rw_proc_new);
  774. /*
  775. */
  776. static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
  777. {
  778. snd_iprintf(buffer,
  779. "Advanced Linux Sound Architecture Driver Version k%s.\n",
  780. init_utsname()->release);
  781. }
  782. static int __init snd_info_version_init(void)
  783. {
  784. struct snd_info_entry *entry;
  785. entry = snd_info_create_module_entry(THIS_MODULE, "version", NULL);
  786. if (entry == NULL)
  787. return -ENOMEM;
  788. entry->c.text.read = snd_info_version_read;
  789. return snd_info_register(entry); /* freed in error path */
  790. }