4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
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
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.
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
21 #include "pvrusb2-context.h"
22 #include "pvrusb2-io.h"
23 #include "pvrusb2-ioread.h"
24 #include "pvrusb2-hdw.h"
25 #include "pvrusb2-debug.h"
26 #include <linux/kthread.h>
27 #include <linux/errno.h>
28 #include <linux/string.h>
29 #include <linux/slab.h>
32 static void pvr2_context_destroy(struct pvr2_context *mp)
34 pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp);
35 if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
40 static void pvr2_context_notify(struct pvr2_context *mp)
43 wake_up(&mp->wait_data);
47 static int pvr2_context_thread(void *_mp)
49 struct pvr2_channel *ch1,*ch2;
50 struct pvr2_context *mp = _mp;
51 pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (thread start)",mp);
53 /* Finish hardware initialization */
54 if (pvr2_hdw_initialize(mp->hdw,
55 (void (*)(void *))pvr2_context_notify,mp)) {
56 mp->video_stream.stream =
57 pvr2_hdw_get_video_stream(mp->hdw);
58 /* Trigger interface initialization. By doing this here
59 initialization runs in our own safe and cozy thread
61 if (mp->setup_func) mp->setup_func(mp);
63 pvr2_trace(PVR2_TRACE_CTXT,
64 "pvr2_context %p (thread skipping setup)",mp);
65 /* Even though initialization did not succeed, we're still
66 going to enter the wait loop anyway. We need to do this
67 in order to await the expected disconnect (which we will
68 detect in the normal course of operation). */
71 /* Now just issue callbacks whenever hardware state changes or if
72 there is a disconnect. If there is a disconnect and there are
73 no channels left, then there's no reason to stick around anymore
74 so we'll self-destruct - tearing down the rest of this driver
75 instance along the way. */
76 pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (thread enter loop)",mp);
77 while (!mp->disconnect_flag || mp->mc_first) {
78 if (mp->notify_flag) {
80 pvr2_trace(PVR2_TRACE_CTXT,
81 "pvr2_context %p (thread notify)",mp);
82 for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
84 if (ch1->check_func) ch1->check_func(ch1);
87 wait_event_interruptible(mp->wait_data, mp->notify_flag);
89 pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (thread end)",mp);
90 pvr2_context_destroy(mp);
95 struct pvr2_context *pvr2_context_create(
96 struct usb_interface *intf,
97 const struct usb_device_id *devid,
98 void (*setup_func)(struct pvr2_context *))
100 struct task_struct *thread;
101 struct pvr2_context *mp = NULL;
102 mp = kzalloc(sizeof(*mp),GFP_KERNEL);
104 pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp);
105 init_waitqueue_head(&mp->wait_data);
106 mp->setup_func = setup_func;
107 mutex_init(&mp->mutex);
108 mp->hdw = pvr2_hdw_create(intf,devid);
110 pvr2_context_destroy(mp);
114 thread = kthread_run(pvr2_context_thread, mp, "pvrusb2-context");
116 pvr2_context_destroy(mp);
125 static void pvr2_context_enter(struct pvr2_context *mp)
127 mutex_lock(&mp->mutex);
131 static void pvr2_context_exit(struct pvr2_context *mp)
133 int destroy_flag = 0;
134 if (!(mp->mc_first || !mp->disconnect_flag)) {
137 mutex_unlock(&mp->mutex);
138 if (destroy_flag) pvr2_context_notify(mp);
142 void pvr2_context_disconnect(struct pvr2_context *mp)
144 pvr2_hdw_disconnect(mp->hdw);
145 mp->disconnect_flag = !0;
146 pvr2_context_notify(mp);
150 void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
152 pvr2_context_enter(mp);
156 cp->mc_prev = mp->mc_last;
158 mp->mc_last->mc_next = cp;
163 pvr2_context_exit(mp);
167 static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
169 if (!cp->stream) return;
170 pvr2_stream_kill(cp->stream->stream);
171 cp->stream->user = NULL;
176 void pvr2_channel_done(struct pvr2_channel *cp)
178 struct pvr2_context *mp = cp->mc_head;
179 pvr2_context_enter(mp);
180 pvr2_channel_disclaim_stream(cp);
182 cp->mc_next->mc_prev = cp->mc_prev;
184 mp->mc_last = cp->mc_prev;
187 cp->mc_prev->mc_next = cp->mc_next;
189 mp->mc_first = cp->mc_next;
192 pvr2_context_exit(mp);
196 int pvr2_channel_claim_stream(struct pvr2_channel *cp,
197 struct pvr2_context_stream *sp)
200 pvr2_context_enter(cp->mc_head); do {
201 if (sp == cp->stream) break;
202 if (sp && sp->user) {
206 pvr2_channel_disclaim_stream(cp);
210 } while (0); pvr2_context_exit(cp->mc_head);
215 // This is the marker for the real beginning of a legitimate mpeg2 stream.
216 static char stream_sync_key[] = {
217 0x00, 0x00, 0x01, 0xba,
220 struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
221 struct pvr2_context_stream *sp)
223 struct pvr2_ioread *cp;
224 cp = pvr2_ioread_create();
225 if (!cp) return NULL;
226 pvr2_ioread_setup(cp,sp->stream);
227 pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key));
233 Stuff for Emacs to see, in order to encourage consistent editing style:
234 *** Local Variables: ***
236 *** fill-column: 75 ***
238 *** c-basic-offset: 8 ***