1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
7 #include "pvrusb2-context.h"
8 #include "pvrusb2-io.h"
9 #include "pvrusb2-ioread.h"
10 #include "pvrusb2-hdw.h"
11 #include "pvrusb2-debug.h"
12 #include <linux/wait.h>
13 #include <linux/kthread.h>
14 #include <linux/errno.h>
15 #include <linux/string.h>
16 #include <linux/slab.h>
18 static struct pvr2_context
*pvr2_context_exist_first
;
19 static struct pvr2_context
*pvr2_context_exist_last
;
20 static struct pvr2_context
*pvr2_context_notify_first
;
21 static struct pvr2_context
*pvr2_context_notify_last
;
22 static DEFINE_MUTEX(pvr2_context_mutex
);
23 static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_sync_data
);
24 static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_cleanup_data
);
25 static int pvr2_context_cleanup_flag
;
26 static int pvr2_context_cleaned_flag
;
27 static struct task_struct
*pvr2_context_thread_ptr
;
30 static void pvr2_context_set_notify(struct pvr2_context
*mp
, int fl
)
33 mutex_lock(&pvr2_context_mutex
);
35 if (!mp
->notify_flag
) {
36 signal_flag
= (pvr2_context_notify_first
== NULL
);
37 mp
->notify_prev
= pvr2_context_notify_last
;
38 mp
->notify_next
= NULL
;
39 pvr2_context_notify_last
= mp
;
40 if (mp
->notify_prev
) {
41 mp
->notify_prev
->notify_next
= mp
;
43 pvr2_context_notify_first
= mp
;
48 if (mp
->notify_flag
) {
50 if (mp
->notify_next
) {
51 mp
->notify_next
->notify_prev
= mp
->notify_prev
;
53 pvr2_context_notify_last
= mp
->notify_prev
;
55 if (mp
->notify_prev
) {
56 mp
->notify_prev
->notify_next
= mp
->notify_next
;
58 pvr2_context_notify_first
= mp
->notify_next
;
62 mutex_unlock(&pvr2_context_mutex
);
63 if (signal_flag
) wake_up(&pvr2_context_sync_data
);
67 static void pvr2_context_destroy(struct pvr2_context
*mp
)
69 pvr2_trace(PVR2_TRACE_CTXT
,"pvr2_context %p (destroy)",mp
);
70 pvr2_hdw_destroy(mp
->hdw
);
71 pvr2_context_set_notify(mp
, 0);
72 mutex_lock(&pvr2_context_mutex
);
74 mp
->exist_next
->exist_prev
= mp
->exist_prev
;
76 pvr2_context_exist_last
= mp
->exist_prev
;
79 mp
->exist_prev
->exist_next
= mp
->exist_next
;
81 pvr2_context_exist_first
= mp
->exist_next
;
83 if (!pvr2_context_exist_first
) {
84 /* Trigger wakeup on control thread in case it is waiting
85 for an exit condition. */
86 wake_up(&pvr2_context_sync_data
);
88 mutex_unlock(&pvr2_context_mutex
);
93 static void pvr2_context_notify(struct pvr2_context
*mp
)
95 pvr2_context_set_notify(mp
,!0);
99 static void pvr2_context_check(struct pvr2_context
*mp
)
101 struct pvr2_channel
*ch1
, *ch2
;
102 pvr2_trace(PVR2_TRACE_CTXT
,
103 "pvr2_context %p (notify)", mp
);
104 if (!mp
->initialized_flag
&& !mp
->disconnect_flag
) {
105 mp
->initialized_flag
= !0;
106 pvr2_trace(PVR2_TRACE_CTXT
,
107 "pvr2_context %p (initialize)", mp
);
108 /* Finish hardware initialization */
109 if (pvr2_hdw_initialize(mp
->hdw
,
110 (void (*)(void *))pvr2_context_notify
,
112 mp
->video_stream
.stream
=
113 pvr2_hdw_get_video_stream(mp
->hdw
);
114 /* Trigger interface initialization. By doing this
115 here initialization runs in our own safe and
116 cozy thread context. */
117 if (mp
->setup_func
) mp
->setup_func(mp
);
119 pvr2_trace(PVR2_TRACE_CTXT
,
120 "pvr2_context %p (thread skipping setup)",
122 /* Even though initialization did not succeed,
123 we're still going to continue anyway. We need
124 to do this in order to await the expected
125 disconnect (which we will detect in the normal
126 course of operation). */
130 for (ch1
= mp
->mc_first
; ch1
; ch1
= ch2
) {
132 if (ch1
->check_func
) ch1
->check_func(ch1
);
135 if (mp
->disconnect_flag
&& !mp
->mc_first
) {
137 pvr2_context_destroy(mp
);
143 static int pvr2_context_shutok(void)
145 return pvr2_context_cleanup_flag
&& (pvr2_context_exist_first
== NULL
);
149 static int pvr2_context_thread_func(void *foo
)
151 struct pvr2_context
*mp
;
153 pvr2_trace(PVR2_TRACE_CTXT
,"pvr2_context thread start");
156 while ((mp
= pvr2_context_notify_first
) != NULL
) {
157 pvr2_context_set_notify(mp
, 0);
158 pvr2_context_check(mp
);
160 wait_event_interruptible(
161 pvr2_context_sync_data
,
162 ((pvr2_context_notify_first
!= NULL
) ||
163 pvr2_context_shutok()));
164 } while (!pvr2_context_shutok());
166 pvr2_context_cleaned_flag
= !0;
167 wake_up(&pvr2_context_cleanup_data
);
169 pvr2_trace(PVR2_TRACE_CTXT
,"pvr2_context thread cleaned up");
171 wait_event_interruptible(
172 pvr2_context_sync_data
,
173 kthread_should_stop());
175 pvr2_trace(PVR2_TRACE_CTXT
,"pvr2_context thread end");
181 int pvr2_context_global_init(void)
183 pvr2_context_thread_ptr
= kthread_run(pvr2_context_thread_func
,
186 return IS_ERR(pvr2_context_thread_ptr
) ? -ENOMEM
: 0;
190 void pvr2_context_global_done(void)
192 pvr2_context_cleanup_flag
= !0;
193 wake_up(&pvr2_context_sync_data
);
194 wait_event_interruptible(
195 pvr2_context_cleanup_data
,
196 pvr2_context_cleaned_flag
);
197 kthread_stop(pvr2_context_thread_ptr
);
201 struct pvr2_context
*pvr2_context_create(
202 struct usb_interface
*intf
,
203 const struct usb_device_id
*devid
,
204 void (*setup_func
)(struct pvr2_context
*))
206 struct pvr2_context
*mp
= NULL
;
207 mp
= kzalloc(sizeof(*mp
),GFP_KERNEL
);
209 pvr2_trace(PVR2_TRACE_CTXT
,"pvr2_context %p (create)",mp
);
210 mp
->setup_func
= setup_func
;
211 mutex_init(&mp
->mutex
);
212 mutex_lock(&pvr2_context_mutex
);
213 mp
->exist_prev
= pvr2_context_exist_last
;
214 mp
->exist_next
= NULL
;
215 pvr2_context_exist_last
= mp
;
216 if (mp
->exist_prev
) {
217 mp
->exist_prev
->exist_next
= mp
;
219 pvr2_context_exist_first
= mp
;
221 mutex_unlock(&pvr2_context_mutex
);
222 mp
->hdw
= pvr2_hdw_create(intf
,devid
);
224 pvr2_context_destroy(mp
);
228 pvr2_context_set_notify(mp
, !0);
234 static void pvr2_context_reset_input_limits(struct pvr2_context
*mp
)
236 unsigned int tmsk
,mmsk
;
237 struct pvr2_channel
*cp
;
238 struct pvr2_hdw
*hdw
= mp
->hdw
;
239 mmsk
= pvr2_hdw_get_input_available(hdw
);
241 for (cp
= mp
->mc_first
; cp
; cp
= cp
->mc_next
) {
242 if (!cp
->input_mask
) continue;
243 tmsk
&= cp
->input_mask
;
245 pvr2_hdw_set_input_allowed(hdw
,mmsk
,tmsk
);
246 pvr2_hdw_commit_ctl(hdw
);
250 static void pvr2_context_enter(struct pvr2_context
*mp
)
252 mutex_lock(&mp
->mutex
);
256 static void pvr2_context_exit(struct pvr2_context
*mp
)
258 int destroy_flag
= 0;
259 if (!(mp
->mc_first
|| !mp
->disconnect_flag
)) {
262 mutex_unlock(&mp
->mutex
);
263 if (destroy_flag
) pvr2_context_notify(mp
);
267 void pvr2_context_disconnect(struct pvr2_context
*mp
)
269 pvr2_hdw_disconnect(mp
->hdw
);
270 mp
->disconnect_flag
= !0;
271 pvr2_context_notify(mp
);
275 void pvr2_channel_init(struct pvr2_channel
*cp
,struct pvr2_context
*mp
)
277 pvr2_context_enter(mp
);
281 cp
->mc_prev
= mp
->mc_last
;
283 mp
->mc_last
->mc_next
= cp
;
288 pvr2_context_exit(mp
);
292 static void pvr2_channel_disclaim_stream(struct pvr2_channel
*cp
)
294 if (!cp
->stream
) return;
295 pvr2_stream_kill(cp
->stream
->stream
);
296 cp
->stream
->user
= NULL
;
301 void pvr2_channel_done(struct pvr2_channel
*cp
)
303 struct pvr2_context
*mp
= cp
->mc_head
;
304 pvr2_context_enter(mp
);
306 pvr2_channel_disclaim_stream(cp
);
307 pvr2_context_reset_input_limits(mp
);
309 cp
->mc_next
->mc_prev
= cp
->mc_prev
;
311 mp
->mc_last
= cp
->mc_prev
;
314 cp
->mc_prev
->mc_next
= cp
->mc_next
;
316 mp
->mc_first
= cp
->mc_next
;
319 pvr2_context_exit(mp
);
323 int pvr2_channel_limit_inputs(struct pvr2_channel
*cp
,unsigned int cmsk
)
325 unsigned int tmsk
,mmsk
;
327 struct pvr2_channel
*p2
;
328 struct pvr2_hdw
*hdw
= cp
->hdw
;
330 mmsk
= pvr2_hdw_get_input_available(hdw
);
332 if (cmsk
== cp
->input_mask
) {
333 /* No change; nothing to do */
337 pvr2_context_enter(cp
->mc_head
);
341 pvr2_context_reset_input_limits(cp
->mc_head
);
345 for (p2
= cp
->mc_head
->mc_first
; p2
; p2
= p2
->mc_next
) {
346 if (p2
== cp
) continue;
347 if (!p2
->input_mask
) continue;
348 tmsk
&= p2
->input_mask
;
350 if (!(tmsk
& cmsk
)) {
355 if ((ret
= pvr2_hdw_set_input_allowed(hdw
,mmsk
,tmsk
)) != 0) {
356 /* Internal failure changing allowed list; probably
357 should not happen, but react if it does. */
360 cp
->input_mask
= cmsk
;
361 pvr2_hdw_commit_ctl(hdw
);
363 pvr2_context_exit(cp
->mc_head
);
368 unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel
*cp
)
370 return cp
->input_mask
;
374 int pvr2_channel_claim_stream(struct pvr2_channel
*cp
,
375 struct pvr2_context_stream
*sp
)
378 pvr2_context_enter(cp
->mc_head
); do {
379 if (sp
== cp
->stream
) break;
380 if (sp
&& sp
->user
) {
384 pvr2_channel_disclaim_stream(cp
);
389 pvr2_context_exit(cp
->mc_head
);
394 // This is the marker for the real beginning of a legitimate mpeg2 stream.
395 static char stream_sync_key
[] = {
396 0x00, 0x00, 0x01, 0xba,
399 struct pvr2_ioread
*pvr2_channel_create_mpeg_stream(
400 struct pvr2_context_stream
*sp
)
402 struct pvr2_ioread
*cp
;
403 cp
= pvr2_ioread_create();
404 if (!cp
) return NULL
;
405 pvr2_ioread_setup(cp
,sp
->stream
);
406 pvr2_ioread_set_sync_key(cp
,stream_sync_key
,sizeof(stream_sync_key
));