devsynth.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #include <linux/errno.h>
  2. #include <linux/miscdevice.h> /* for misc_register, and SYNTH_MINOR */
  3. #include <linux/types.h>
  4. #include <linux/uaccess.h>
  5. #include "speakup.h"
  6. #include "spk_priv.h"
  7. #ifndef SYNTH_MINOR
  8. #define SYNTH_MINOR 25
  9. #endif
  10. static int misc_registered;
  11. static int dev_opened;
  12. static ssize_t speakup_file_write(struct file *fp, const char __user *buffer,
  13. size_t nbytes, loff_t *ppos)
  14. {
  15. size_t count = nbytes;
  16. const char __user *ptr = buffer;
  17. size_t bytes;
  18. unsigned long flags;
  19. u_char buf[256];
  20. if (!synth)
  21. return -ENODEV;
  22. while (count > 0) {
  23. bytes = min(count, sizeof(buf));
  24. if (copy_from_user(buf, ptr, bytes))
  25. return -EFAULT;
  26. count -= bytes;
  27. ptr += bytes;
  28. spin_lock_irqsave(&speakup_info.spinlock, flags);
  29. synth_write(buf, bytes);
  30. spin_unlock_irqrestore(&speakup_info.spinlock, flags);
  31. }
  32. return (ssize_t) nbytes;
  33. }
  34. static ssize_t speakup_file_read(struct file *fp, char __user *buf,
  35. size_t nbytes, loff_t *ppos)
  36. {
  37. return 0;
  38. }
  39. static int speakup_file_open(struct inode *ip, struct file *fp)
  40. {
  41. if (!synth)
  42. return -ENODEV;
  43. if (xchg(&dev_opened, 1))
  44. return -EBUSY;
  45. return 0;
  46. }
  47. static int speakup_file_release(struct inode *ip, struct file *fp)
  48. {
  49. dev_opened = 0;
  50. return 0;
  51. }
  52. static const struct file_operations synth_fops = {
  53. .read = speakup_file_read,
  54. .write = speakup_file_write,
  55. .open = speakup_file_open,
  56. .release = speakup_file_release,
  57. };
  58. static struct miscdevice synth_device = {
  59. .minor = SYNTH_MINOR,
  60. .name = "synth",
  61. .fops = &synth_fops,
  62. };
  63. void speakup_register_devsynth(void)
  64. {
  65. if (misc_registered != 0)
  66. return;
  67. /* zero it so if register fails, deregister will not ref invalid ptrs */
  68. if (misc_register(&synth_device))
  69. pr_warn("Couldn't initialize miscdevice /dev/synth.\n");
  70. else {
  71. pr_info("initialized device: /dev/synth, node (MAJOR %d, MINOR %d)\n",
  72. MISC_MAJOR, SYNTH_MINOR);
  73. misc_registered = 1;
  74. }
  75. }
  76. void speakup_unregister_devsynth(void)
  77. {
  78. if (!misc_registered)
  79. return;
  80. pr_info("speakup: unregistering synth device /dev/synth\n");
  81. misc_deregister(&synth_device);
  82. misc_registered = 0;
  83. }