dumprequest.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * Line6 Linux USB driver - 0.9.1beta
  3. *
  4. * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation, version 2.
  9. *
  10. */
  11. #include <linux/slab.h>
  12. #include "driver.h"
  13. #include "dumprequest.h"
  14. /*
  15. Set "dump in progress" flag.
  16. */
  17. void line6_dump_started(struct line6_dump_request *l6dr, int dest)
  18. {
  19. l6dr->in_progress = dest;
  20. }
  21. /*
  22. Invalidate current channel, i.e., set "dump in progress" flag.
  23. Reading from the "dump" special file blocks until dump is completed.
  24. */
  25. void line6_invalidate_current(struct line6_dump_request *l6dr)
  26. {
  27. line6_dump_started(l6dr, LINE6_DUMP_CURRENT);
  28. }
  29. /*
  30. Clear "dump in progress" flag and notify waiting processes.
  31. */
  32. void line6_dump_finished(struct line6_dump_request *l6dr)
  33. {
  34. l6dr->in_progress = LINE6_DUMP_NONE;
  35. wake_up(&l6dr->wait);
  36. }
  37. /*
  38. Send an asynchronous channel dump request.
  39. */
  40. int line6_dump_request_async(struct line6_dump_request *l6dr,
  41. struct usb_line6 *line6, int num, int dest)
  42. {
  43. int ret;
  44. line6_dump_started(l6dr, dest);
  45. ret = line6_send_raw_message_async(line6, l6dr->reqbufs[num].buffer,
  46. l6dr->reqbufs[num].length);
  47. if (ret < 0)
  48. line6_dump_finished(l6dr);
  49. return ret;
  50. }
  51. /*
  52. Wait for completion (interruptible).
  53. */
  54. int line6_dump_wait_interruptible(struct line6_dump_request *l6dr)
  55. {
  56. return wait_event_interruptible(l6dr->wait,
  57. l6dr->in_progress == LINE6_DUMP_NONE);
  58. }
  59. /*
  60. Wait for completion.
  61. */
  62. void line6_dump_wait(struct line6_dump_request *l6dr)
  63. {
  64. wait_event(l6dr->wait, l6dr->in_progress == LINE6_DUMP_NONE);
  65. }
  66. /*
  67. Wait for completion (with timeout).
  68. */
  69. int line6_dump_wait_timeout(struct line6_dump_request *l6dr, long timeout)
  70. {
  71. return wait_event_timeout(l6dr->wait,
  72. l6dr->in_progress == LINE6_DUMP_NONE,
  73. timeout);
  74. }
  75. /*
  76. Initialize dump request buffer.
  77. */
  78. int line6_dumpreq_initbuf(struct line6_dump_request *l6dr, const void *buf,
  79. size_t len, int num)
  80. {
  81. l6dr->reqbufs[num].buffer = kmemdup(buf, len, GFP_KERNEL);
  82. if (l6dr->reqbufs[num].buffer == NULL)
  83. return -ENOMEM;
  84. l6dr->reqbufs[num].length = len;
  85. return 0;
  86. }
  87. /*
  88. Initialize dump request data structure (including one buffer).
  89. */
  90. int line6_dumpreq_init(struct line6_dump_request *l6dr, const void *buf,
  91. size_t len)
  92. {
  93. int ret;
  94. ret = line6_dumpreq_initbuf(l6dr, buf, len, 0);
  95. if (ret < 0)
  96. return ret;
  97. init_waitqueue_head(&l6dr->wait);
  98. return 0;
  99. }
  100. /*
  101. Destruct dump request data structure.
  102. */
  103. void line6_dumpreq_destructbuf(struct line6_dump_request *l6dr, int num)
  104. {
  105. if (l6dr == NULL)
  106. return;
  107. if (l6dr->reqbufs[num].buffer == NULL)
  108. return;
  109. kfree(l6dr->reqbufs[num].buffer);
  110. l6dr->reqbufs[num].buffer = NULL;
  111. }
  112. /*
  113. Destruct dump request data structure.
  114. */
  115. void line6_dumpreq_destruct(struct line6_dump_request *l6dr)
  116. {
  117. if (l6dr->reqbufs[0].buffer == NULL)
  118. return;
  119. line6_dumpreq_destructbuf(l6dr, 0);
  120. }