1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2005 Mike Isely <isely@pobox.com>
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include "pvrusb2-context.h"
8*4882a593Smuzhiyun #include "pvrusb2-io.h"
9*4882a593Smuzhiyun #include "pvrusb2-ioread.h"
10*4882a593Smuzhiyun #include "pvrusb2-hdw.h"
11*4882a593Smuzhiyun #include "pvrusb2-debug.h"
12*4882a593Smuzhiyun #include <linux/wait.h>
13*4882a593Smuzhiyun #include <linux/kthread.h>
14*4882a593Smuzhiyun #include <linux/errno.h>
15*4882a593Smuzhiyun #include <linux/string.h>
16*4882a593Smuzhiyun #include <linux/slab.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun static struct pvr2_context *pvr2_context_exist_first;
19*4882a593Smuzhiyun static struct pvr2_context *pvr2_context_exist_last;
20*4882a593Smuzhiyun static struct pvr2_context *pvr2_context_notify_first;
21*4882a593Smuzhiyun static struct pvr2_context *pvr2_context_notify_last;
22*4882a593Smuzhiyun static DEFINE_MUTEX(pvr2_context_mutex);
23*4882a593Smuzhiyun static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_sync_data);
24*4882a593Smuzhiyun static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_cleanup_data);
25*4882a593Smuzhiyun static int pvr2_context_cleanup_flag;
26*4882a593Smuzhiyun static int pvr2_context_cleaned_flag;
27*4882a593Smuzhiyun static struct task_struct *pvr2_context_thread_ptr;
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun
pvr2_context_set_notify(struct pvr2_context * mp,int fl)30*4882a593Smuzhiyun static void pvr2_context_set_notify(struct pvr2_context *mp, int fl)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun int signal_flag = 0;
33*4882a593Smuzhiyun mutex_lock(&pvr2_context_mutex);
34*4882a593Smuzhiyun if (fl) {
35*4882a593Smuzhiyun if (!mp->notify_flag) {
36*4882a593Smuzhiyun signal_flag = (pvr2_context_notify_first == NULL);
37*4882a593Smuzhiyun mp->notify_prev = pvr2_context_notify_last;
38*4882a593Smuzhiyun mp->notify_next = NULL;
39*4882a593Smuzhiyun pvr2_context_notify_last = mp;
40*4882a593Smuzhiyun if (mp->notify_prev) {
41*4882a593Smuzhiyun mp->notify_prev->notify_next = mp;
42*4882a593Smuzhiyun } else {
43*4882a593Smuzhiyun pvr2_context_notify_first = mp;
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun mp->notify_flag = !0;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun } else {
48*4882a593Smuzhiyun if (mp->notify_flag) {
49*4882a593Smuzhiyun mp->notify_flag = 0;
50*4882a593Smuzhiyun if (mp->notify_next) {
51*4882a593Smuzhiyun mp->notify_next->notify_prev = mp->notify_prev;
52*4882a593Smuzhiyun } else {
53*4882a593Smuzhiyun pvr2_context_notify_last = mp->notify_prev;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun if (mp->notify_prev) {
56*4882a593Smuzhiyun mp->notify_prev->notify_next = mp->notify_next;
57*4882a593Smuzhiyun } else {
58*4882a593Smuzhiyun pvr2_context_notify_first = mp->notify_next;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun mutex_unlock(&pvr2_context_mutex);
63*4882a593Smuzhiyun if (signal_flag) wake_up(&pvr2_context_sync_data);
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun
pvr2_context_destroy(struct pvr2_context * mp)67*4882a593Smuzhiyun static void pvr2_context_destroy(struct pvr2_context *mp)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp);
70*4882a593Smuzhiyun pvr2_hdw_destroy(mp->hdw);
71*4882a593Smuzhiyun pvr2_context_set_notify(mp, 0);
72*4882a593Smuzhiyun mutex_lock(&pvr2_context_mutex);
73*4882a593Smuzhiyun if (mp->exist_next) {
74*4882a593Smuzhiyun mp->exist_next->exist_prev = mp->exist_prev;
75*4882a593Smuzhiyun } else {
76*4882a593Smuzhiyun pvr2_context_exist_last = mp->exist_prev;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun if (mp->exist_prev) {
79*4882a593Smuzhiyun mp->exist_prev->exist_next = mp->exist_next;
80*4882a593Smuzhiyun } else {
81*4882a593Smuzhiyun pvr2_context_exist_first = mp->exist_next;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun if (!pvr2_context_exist_first) {
84*4882a593Smuzhiyun /* Trigger wakeup on control thread in case it is waiting
85*4882a593Smuzhiyun for an exit condition. */
86*4882a593Smuzhiyun wake_up(&pvr2_context_sync_data);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun mutex_unlock(&pvr2_context_mutex);
89*4882a593Smuzhiyun kfree(mp);
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun
pvr2_context_notify(struct pvr2_context * mp)93*4882a593Smuzhiyun static void pvr2_context_notify(struct pvr2_context *mp)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun pvr2_context_set_notify(mp,!0);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun
pvr2_context_check(struct pvr2_context * mp)99*4882a593Smuzhiyun static void pvr2_context_check(struct pvr2_context *mp)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun struct pvr2_channel *ch1, *ch2;
102*4882a593Smuzhiyun pvr2_trace(PVR2_TRACE_CTXT,
103*4882a593Smuzhiyun "pvr2_context %p (notify)", mp);
104*4882a593Smuzhiyun if (!mp->initialized_flag && !mp->disconnect_flag) {
105*4882a593Smuzhiyun mp->initialized_flag = !0;
106*4882a593Smuzhiyun pvr2_trace(PVR2_TRACE_CTXT,
107*4882a593Smuzhiyun "pvr2_context %p (initialize)", mp);
108*4882a593Smuzhiyun /* Finish hardware initialization */
109*4882a593Smuzhiyun if (pvr2_hdw_initialize(mp->hdw,
110*4882a593Smuzhiyun (void (*)(void *))pvr2_context_notify,
111*4882a593Smuzhiyun mp)) {
112*4882a593Smuzhiyun mp->video_stream.stream =
113*4882a593Smuzhiyun pvr2_hdw_get_video_stream(mp->hdw);
114*4882a593Smuzhiyun /* Trigger interface initialization. By doing this
115*4882a593Smuzhiyun here initialization runs in our own safe and
116*4882a593Smuzhiyun cozy thread context. */
117*4882a593Smuzhiyun if (mp->setup_func) mp->setup_func(mp);
118*4882a593Smuzhiyun } else {
119*4882a593Smuzhiyun pvr2_trace(PVR2_TRACE_CTXT,
120*4882a593Smuzhiyun "pvr2_context %p (thread skipping setup)",
121*4882a593Smuzhiyun mp);
122*4882a593Smuzhiyun /* Even though initialization did not succeed,
123*4882a593Smuzhiyun we're still going to continue anyway. We need
124*4882a593Smuzhiyun to do this in order to await the expected
125*4882a593Smuzhiyun disconnect (which we will detect in the normal
126*4882a593Smuzhiyun course of operation). */
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
131*4882a593Smuzhiyun ch2 = ch1->mc_next;
132*4882a593Smuzhiyun if (ch1->check_func) ch1->check_func(ch1);
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun if (mp->disconnect_flag && !mp->mc_first) {
136*4882a593Smuzhiyun /* Go away... */
137*4882a593Smuzhiyun pvr2_context_destroy(mp);
138*4882a593Smuzhiyun return;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun
pvr2_context_shutok(void)143*4882a593Smuzhiyun static int pvr2_context_shutok(void)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun return pvr2_context_cleanup_flag && (pvr2_context_exist_first == NULL);
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun
pvr2_context_thread_func(void * foo)149*4882a593Smuzhiyun static int pvr2_context_thread_func(void *foo)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun struct pvr2_context *mp;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread start");
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun do {
156*4882a593Smuzhiyun while ((mp = pvr2_context_notify_first) != NULL) {
157*4882a593Smuzhiyun pvr2_context_set_notify(mp, 0);
158*4882a593Smuzhiyun pvr2_context_check(mp);
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun wait_event_interruptible(
161*4882a593Smuzhiyun pvr2_context_sync_data,
162*4882a593Smuzhiyun ((pvr2_context_notify_first != NULL) ||
163*4882a593Smuzhiyun pvr2_context_shutok()));
164*4882a593Smuzhiyun } while (!pvr2_context_shutok());
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun pvr2_context_cleaned_flag = !0;
167*4882a593Smuzhiyun wake_up(&pvr2_context_cleanup_data);
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread cleaned up");
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun wait_event_interruptible(
172*4882a593Smuzhiyun pvr2_context_sync_data,
173*4882a593Smuzhiyun kthread_should_stop());
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end");
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun return 0;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun
pvr2_context_global_init(void)181*4882a593Smuzhiyun int pvr2_context_global_init(void)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func,
184*4882a593Smuzhiyun NULL,
185*4882a593Smuzhiyun "pvrusb2-context");
186*4882a593Smuzhiyun return IS_ERR(pvr2_context_thread_ptr) ? -ENOMEM : 0;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun
pvr2_context_global_done(void)190*4882a593Smuzhiyun void pvr2_context_global_done(void)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun pvr2_context_cleanup_flag = !0;
193*4882a593Smuzhiyun wake_up(&pvr2_context_sync_data);
194*4882a593Smuzhiyun wait_event_interruptible(
195*4882a593Smuzhiyun pvr2_context_cleanup_data,
196*4882a593Smuzhiyun pvr2_context_cleaned_flag);
197*4882a593Smuzhiyun kthread_stop(pvr2_context_thread_ptr);
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun
pvr2_context_create(struct usb_interface * intf,const struct usb_device_id * devid,void (* setup_func)(struct pvr2_context *))201*4882a593Smuzhiyun struct pvr2_context *pvr2_context_create(
202*4882a593Smuzhiyun struct usb_interface *intf,
203*4882a593Smuzhiyun const struct usb_device_id *devid,
204*4882a593Smuzhiyun void (*setup_func)(struct pvr2_context *))
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun struct pvr2_context *mp = NULL;
207*4882a593Smuzhiyun mp = kzalloc(sizeof(*mp),GFP_KERNEL);
208*4882a593Smuzhiyun if (!mp) goto done;
209*4882a593Smuzhiyun pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp);
210*4882a593Smuzhiyun mp->setup_func = setup_func;
211*4882a593Smuzhiyun mutex_init(&mp->mutex);
212*4882a593Smuzhiyun mutex_lock(&pvr2_context_mutex);
213*4882a593Smuzhiyun mp->exist_prev = pvr2_context_exist_last;
214*4882a593Smuzhiyun mp->exist_next = NULL;
215*4882a593Smuzhiyun pvr2_context_exist_last = mp;
216*4882a593Smuzhiyun if (mp->exist_prev) {
217*4882a593Smuzhiyun mp->exist_prev->exist_next = mp;
218*4882a593Smuzhiyun } else {
219*4882a593Smuzhiyun pvr2_context_exist_first = mp;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun mutex_unlock(&pvr2_context_mutex);
222*4882a593Smuzhiyun mp->hdw = pvr2_hdw_create(intf,devid);
223*4882a593Smuzhiyun if (!mp->hdw) {
224*4882a593Smuzhiyun pvr2_context_destroy(mp);
225*4882a593Smuzhiyun mp = NULL;
226*4882a593Smuzhiyun goto done;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun pvr2_context_set_notify(mp, !0);
229*4882a593Smuzhiyun done:
230*4882a593Smuzhiyun return mp;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun
pvr2_context_reset_input_limits(struct pvr2_context * mp)234*4882a593Smuzhiyun static void pvr2_context_reset_input_limits(struct pvr2_context *mp)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun unsigned int tmsk,mmsk;
237*4882a593Smuzhiyun struct pvr2_channel *cp;
238*4882a593Smuzhiyun struct pvr2_hdw *hdw = mp->hdw;
239*4882a593Smuzhiyun mmsk = pvr2_hdw_get_input_available(hdw);
240*4882a593Smuzhiyun tmsk = mmsk;
241*4882a593Smuzhiyun for (cp = mp->mc_first; cp; cp = cp->mc_next) {
242*4882a593Smuzhiyun if (!cp->input_mask) continue;
243*4882a593Smuzhiyun tmsk &= cp->input_mask;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk);
246*4882a593Smuzhiyun pvr2_hdw_commit_ctl(hdw);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun
pvr2_context_enter(struct pvr2_context * mp)250*4882a593Smuzhiyun static void pvr2_context_enter(struct pvr2_context *mp)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun mutex_lock(&mp->mutex);
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun
pvr2_context_exit(struct pvr2_context * mp)256*4882a593Smuzhiyun static void pvr2_context_exit(struct pvr2_context *mp)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun int destroy_flag = 0;
259*4882a593Smuzhiyun if (!(mp->mc_first || !mp->disconnect_flag)) {
260*4882a593Smuzhiyun destroy_flag = !0;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun mutex_unlock(&mp->mutex);
263*4882a593Smuzhiyun if (destroy_flag) pvr2_context_notify(mp);
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun
pvr2_context_disconnect(struct pvr2_context * mp)267*4882a593Smuzhiyun void pvr2_context_disconnect(struct pvr2_context *mp)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun pvr2_hdw_disconnect(mp->hdw);
270*4882a593Smuzhiyun mp->disconnect_flag = !0;
271*4882a593Smuzhiyun pvr2_context_notify(mp);
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun
pvr2_channel_init(struct pvr2_channel * cp,struct pvr2_context * mp)275*4882a593Smuzhiyun void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun pvr2_context_enter(mp);
278*4882a593Smuzhiyun cp->hdw = mp->hdw;
279*4882a593Smuzhiyun cp->mc_head = mp;
280*4882a593Smuzhiyun cp->mc_next = NULL;
281*4882a593Smuzhiyun cp->mc_prev = mp->mc_last;
282*4882a593Smuzhiyun if (mp->mc_last) {
283*4882a593Smuzhiyun mp->mc_last->mc_next = cp;
284*4882a593Smuzhiyun } else {
285*4882a593Smuzhiyun mp->mc_first = cp;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun mp->mc_last = cp;
288*4882a593Smuzhiyun pvr2_context_exit(mp);
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun
pvr2_channel_disclaim_stream(struct pvr2_channel * cp)292*4882a593Smuzhiyun static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun if (!cp->stream) return;
295*4882a593Smuzhiyun pvr2_stream_kill(cp->stream->stream);
296*4882a593Smuzhiyun cp->stream->user = NULL;
297*4882a593Smuzhiyun cp->stream = NULL;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun
pvr2_channel_done(struct pvr2_channel * cp)301*4882a593Smuzhiyun void pvr2_channel_done(struct pvr2_channel *cp)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun struct pvr2_context *mp = cp->mc_head;
304*4882a593Smuzhiyun pvr2_context_enter(mp);
305*4882a593Smuzhiyun cp->input_mask = 0;
306*4882a593Smuzhiyun pvr2_channel_disclaim_stream(cp);
307*4882a593Smuzhiyun pvr2_context_reset_input_limits(mp);
308*4882a593Smuzhiyun if (cp->mc_next) {
309*4882a593Smuzhiyun cp->mc_next->mc_prev = cp->mc_prev;
310*4882a593Smuzhiyun } else {
311*4882a593Smuzhiyun mp->mc_last = cp->mc_prev;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun if (cp->mc_prev) {
314*4882a593Smuzhiyun cp->mc_prev->mc_next = cp->mc_next;
315*4882a593Smuzhiyun } else {
316*4882a593Smuzhiyun mp->mc_first = cp->mc_next;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun cp->hdw = NULL;
319*4882a593Smuzhiyun pvr2_context_exit(mp);
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun
pvr2_channel_limit_inputs(struct pvr2_channel * cp,unsigned int cmsk)323*4882a593Smuzhiyun int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun unsigned int tmsk,mmsk;
326*4882a593Smuzhiyun int ret = 0;
327*4882a593Smuzhiyun struct pvr2_channel *p2;
328*4882a593Smuzhiyun struct pvr2_hdw *hdw = cp->hdw;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun mmsk = pvr2_hdw_get_input_available(hdw);
331*4882a593Smuzhiyun cmsk &= mmsk;
332*4882a593Smuzhiyun if (cmsk == cp->input_mask) {
333*4882a593Smuzhiyun /* No change; nothing to do */
334*4882a593Smuzhiyun return 0;
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun pvr2_context_enter(cp->mc_head);
338*4882a593Smuzhiyun do {
339*4882a593Smuzhiyun if (!cmsk) {
340*4882a593Smuzhiyun cp->input_mask = 0;
341*4882a593Smuzhiyun pvr2_context_reset_input_limits(cp->mc_head);
342*4882a593Smuzhiyun break;
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun tmsk = mmsk;
345*4882a593Smuzhiyun for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) {
346*4882a593Smuzhiyun if (p2 == cp) continue;
347*4882a593Smuzhiyun if (!p2->input_mask) continue;
348*4882a593Smuzhiyun tmsk &= p2->input_mask;
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun if (!(tmsk & cmsk)) {
351*4882a593Smuzhiyun ret = -EPERM;
352*4882a593Smuzhiyun break;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun tmsk &= cmsk;
355*4882a593Smuzhiyun if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) {
356*4882a593Smuzhiyun /* Internal failure changing allowed list; probably
357*4882a593Smuzhiyun should not happen, but react if it does. */
358*4882a593Smuzhiyun break;
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun cp->input_mask = cmsk;
361*4882a593Smuzhiyun pvr2_hdw_commit_ctl(hdw);
362*4882a593Smuzhiyun } while (0);
363*4882a593Smuzhiyun pvr2_context_exit(cp->mc_head);
364*4882a593Smuzhiyun return ret;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun
pvr2_channel_get_limited_inputs(struct pvr2_channel * cp)368*4882a593Smuzhiyun unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun return cp->input_mask;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun
pvr2_channel_claim_stream(struct pvr2_channel * cp,struct pvr2_context_stream * sp)374*4882a593Smuzhiyun int pvr2_channel_claim_stream(struct pvr2_channel *cp,
375*4882a593Smuzhiyun struct pvr2_context_stream *sp)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun int code = 0;
378*4882a593Smuzhiyun pvr2_context_enter(cp->mc_head); do {
379*4882a593Smuzhiyun if (sp == cp->stream) break;
380*4882a593Smuzhiyun if (sp && sp->user) {
381*4882a593Smuzhiyun code = -EBUSY;
382*4882a593Smuzhiyun break;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun pvr2_channel_disclaim_stream(cp);
385*4882a593Smuzhiyun if (!sp) break;
386*4882a593Smuzhiyun sp->user = cp;
387*4882a593Smuzhiyun cp->stream = sp;
388*4882a593Smuzhiyun } while (0);
389*4882a593Smuzhiyun pvr2_context_exit(cp->mc_head);
390*4882a593Smuzhiyun return code;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun // This is the marker for the real beginning of a legitimate mpeg2 stream.
395*4882a593Smuzhiyun static char stream_sync_key[] = {
396*4882a593Smuzhiyun 0x00, 0x00, 0x01, 0xba,
397*4882a593Smuzhiyun };
398*4882a593Smuzhiyun
pvr2_channel_create_mpeg_stream(struct pvr2_context_stream * sp)399*4882a593Smuzhiyun struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
400*4882a593Smuzhiyun struct pvr2_context_stream *sp)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun struct pvr2_ioread *cp;
403*4882a593Smuzhiyun cp = pvr2_ioread_create();
404*4882a593Smuzhiyun if (!cp) return NULL;
405*4882a593Smuzhiyun pvr2_ioread_setup(cp,sp->stream);
406*4882a593Smuzhiyun pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key));
407*4882a593Smuzhiyun return cp;
408*4882a593Smuzhiyun }
409