pvrusb2-context.c 5.4 KB

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