pvrusb2-context.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2005 Mike Isely <isely@pobox.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License
  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 "pvrusb2-context.h"
  21. #include "pvrusb2-io.h"
  22. #include "pvrusb2-ioread.h"
  23. #include "pvrusb2-hdw.h"
  24. #include "pvrusb2-debug.h"
  25. #include <linux/errno.h>
  26. #include <linux/string.h>
  27. #include <linux/slab.h>
  28. #include <asm/semaphore.h>
  29. static void pvr2_context_destroy(struct pvr2_context *mp)
  30. {
  31. if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
  32. pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp);
  33. if (mp->workqueue) {
  34. flush_workqueue(mp->workqueue);
  35. destroy_workqueue(mp->workqueue);
  36. }
  37. kfree(mp);
  38. }
  39. static void pvr2_context_trigger_poll(struct pvr2_context *mp)
  40. {
  41. queue_work(mp->workqueue,&mp->workpoll);
  42. }
  43. static void pvr2_context_poll(struct work_struct *work)
  44. {
  45. struct pvr2_context *mp =
  46. container_of(work, struct pvr2_context, workpoll);
  47. pvr2_context_enter(mp); do {
  48. pvr2_hdw_poll(mp->hdw);
  49. } while (0); pvr2_context_exit(mp);
  50. }
  51. static void pvr2_context_setup(struct work_struct *work)
  52. {
  53. struct pvr2_context *mp =
  54. container_of(work, struct pvr2_context, workinit);
  55. pvr2_context_enter(mp); do {
  56. if (!pvr2_hdw_dev_ok(mp->hdw)) break;
  57. pvr2_hdw_setup(mp->hdw);
  58. pvr2_hdw_setup_poll_trigger(
  59. mp->hdw,
  60. (void (*)(void *))pvr2_context_trigger_poll,
  61. mp);
  62. if (!pvr2_hdw_dev_ok(mp->hdw)) break;
  63. if (!pvr2_hdw_init_ok(mp->hdw)) break;
  64. mp->video_stream.stream = pvr2_hdw_get_video_stream(mp->hdw);
  65. if (mp->setup_func) {
  66. mp->setup_func(mp);
  67. }
  68. } while (0); pvr2_context_exit(mp);
  69. }
  70. struct pvr2_context *pvr2_context_create(
  71. struct usb_interface *intf,
  72. const struct usb_device_id *devid,
  73. void (*setup_func)(struct pvr2_context *))
  74. {
  75. struct pvr2_context *mp = NULL;
  76. mp = kzalloc(sizeof(*mp),GFP_KERNEL);
  77. if (!mp) goto done;
  78. pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp);
  79. mp->setup_func = setup_func;
  80. mutex_init(&mp->mutex);
  81. mp->hdw = pvr2_hdw_create(intf,devid);
  82. if (!mp->hdw) {
  83. pvr2_context_destroy(mp);
  84. mp = NULL;
  85. goto done;
  86. }
  87. mp->workqueue = create_singlethread_workqueue("pvrusb2");
  88. INIT_WORK(&mp->workinit, pvr2_context_setup);
  89. INIT_WORK(&mp->workpoll, pvr2_context_poll);
  90. queue_work(mp->workqueue,&mp->workinit);
  91. done:
  92. return mp;
  93. }
  94. void pvr2_context_enter(struct pvr2_context *mp)
  95. {
  96. mutex_lock(&mp->mutex);
  97. pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_enter(id=%p)",mp);
  98. }
  99. void pvr2_context_exit(struct pvr2_context *mp)
  100. {
  101. int destroy_flag = 0;
  102. if (!(mp->mc_first || !mp->disconnect_flag)) {
  103. destroy_flag = !0;
  104. }
  105. pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_exit(id=%p) outside",mp);
  106. mutex_unlock(&mp->mutex);
  107. if (destroy_flag) pvr2_context_destroy(mp);
  108. }
  109. static void pvr2_context_run_checks(struct pvr2_context *mp)
  110. {
  111. struct pvr2_channel *ch1,*ch2;
  112. for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
  113. ch2 = ch1->mc_next;
  114. if (ch1->check_func) {
  115. ch1->check_func(ch1);
  116. }
  117. }
  118. }
  119. void pvr2_context_disconnect(struct pvr2_context *mp)
  120. {
  121. pvr2_context_enter(mp); do {
  122. pvr2_hdw_disconnect(mp->hdw);
  123. mp->disconnect_flag = !0;
  124. pvr2_context_run_checks(mp);
  125. } while (0); pvr2_context_exit(mp);
  126. }
  127. void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
  128. {
  129. cp->hdw = mp->hdw;
  130. cp->mc_head = mp;
  131. cp->mc_next = NULL;
  132. cp->mc_prev = mp->mc_last;
  133. if (mp->mc_last) {
  134. mp->mc_last->mc_next = cp;
  135. } else {
  136. mp->mc_first = cp;
  137. }
  138. mp->mc_last = cp;
  139. }
  140. static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
  141. {
  142. if (!cp->stream) return;
  143. pvr2_stream_kill(cp->stream->stream);
  144. cp->stream->user = NULL;
  145. cp->stream = NULL;
  146. }
  147. void pvr2_channel_done(struct pvr2_channel *cp)
  148. {
  149. struct pvr2_context *mp = cp->mc_head;
  150. pvr2_channel_disclaim_stream(cp);
  151. if (cp->mc_next) {
  152. cp->mc_next->mc_prev = cp->mc_prev;
  153. } else {
  154. mp->mc_last = cp->mc_prev;
  155. }
  156. if (cp->mc_prev) {
  157. cp->mc_prev->mc_next = cp->mc_next;
  158. } else {
  159. mp->mc_first = cp->mc_next;
  160. }
  161. cp->hdw = NULL;
  162. }
  163. int pvr2_channel_claim_stream(struct pvr2_channel *cp,
  164. struct pvr2_context_stream *sp)
  165. {
  166. int code = 0;
  167. pvr2_context_enter(cp->mc_head); do {
  168. if (sp == cp->stream) break;
  169. if (sp->user) {
  170. code = -EBUSY;
  171. break;
  172. }
  173. pvr2_channel_disclaim_stream(cp);
  174. if (!sp) break;
  175. sp->user = cp;
  176. cp->stream = sp;
  177. } while (0); pvr2_context_exit(cp->mc_head);
  178. return code;
  179. }
  180. // This is the marker for the real beginning of a legitimate mpeg2 stream.
  181. static char stream_sync_key[] = {
  182. 0x00, 0x00, 0x01, 0xba,
  183. };
  184. struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
  185. struct pvr2_context_stream *sp)
  186. {
  187. struct pvr2_ioread *cp;
  188. cp = pvr2_ioread_create();
  189. if (!cp) return NULL;
  190. pvr2_ioread_setup(cp,sp->stream);
  191. pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key));
  192. return cp;
  193. }
  194. /*
  195. Stuff for Emacs to see, in order to encourage consistent editing style:
  196. *** Local Variables: ***
  197. *** mode: c ***
  198. *** fill-column: 75 ***
  199. *** tab-width: 8 ***
  200. *** c-basic-offset: 8 ***
  201. *** End: ***
  202. */