pvrusb2-context.c 5.3 KB

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