pvrusb2-context.c 5.5 KB

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