Linux 4.16.11
[linux/fpc-iii.git] / drivers / media / usb / pvrusb2 / pvrusb2-context.c
blobd9e8481e9e286e5f2d6dc7584155e995d7541cc2
1 /*
3 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include "pvrusb2-context.h"
17 #include "pvrusb2-io.h"
18 #include "pvrusb2-ioread.h"
19 #include "pvrusb2-hdw.h"
20 #include "pvrusb2-debug.h"
21 #include <linux/wait.h>
22 #include <linux/kthread.h>
23 #include <linux/errno.h>
24 #include <linux/string.h>
25 #include <linux/slab.h>
27 static struct pvr2_context *pvr2_context_exist_first;
28 static struct pvr2_context *pvr2_context_exist_last;
29 static struct pvr2_context *pvr2_context_notify_first;
30 static struct pvr2_context *pvr2_context_notify_last;
31 static DEFINE_MUTEX(pvr2_context_mutex);
32 static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_sync_data);
33 static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_cleanup_data);
34 static int pvr2_context_cleanup_flag;
35 static int pvr2_context_cleaned_flag;
36 static struct task_struct *pvr2_context_thread_ptr;
39 static void pvr2_context_set_notify(struct pvr2_context *mp, int fl)
41 int signal_flag = 0;
42 mutex_lock(&pvr2_context_mutex);
43 if (fl) {
44 if (!mp->notify_flag) {
45 signal_flag = (pvr2_context_notify_first == NULL);
46 mp->notify_prev = pvr2_context_notify_last;
47 mp->notify_next = NULL;
48 pvr2_context_notify_last = mp;
49 if (mp->notify_prev) {
50 mp->notify_prev->notify_next = mp;
51 } else {
52 pvr2_context_notify_first = mp;
54 mp->notify_flag = !0;
56 } else {
57 if (mp->notify_flag) {
58 mp->notify_flag = 0;
59 if (mp->notify_next) {
60 mp->notify_next->notify_prev = mp->notify_prev;
61 } else {
62 pvr2_context_notify_last = mp->notify_prev;
64 if (mp->notify_prev) {
65 mp->notify_prev->notify_next = mp->notify_next;
66 } else {
67 pvr2_context_notify_first = mp->notify_next;
71 mutex_unlock(&pvr2_context_mutex);
72 if (signal_flag) wake_up(&pvr2_context_sync_data);
76 static void pvr2_context_destroy(struct pvr2_context *mp)
78 pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp);
79 pvr2_hdw_destroy(mp->hdw);
80 pvr2_context_set_notify(mp, 0);
81 mutex_lock(&pvr2_context_mutex);
82 if (mp->exist_next) {
83 mp->exist_next->exist_prev = mp->exist_prev;
84 } else {
85 pvr2_context_exist_last = mp->exist_prev;
87 if (mp->exist_prev) {
88 mp->exist_prev->exist_next = mp->exist_next;
89 } else {
90 pvr2_context_exist_first = mp->exist_next;
92 if (!pvr2_context_exist_first) {
93 /* Trigger wakeup on control thread in case it is waiting
94 for an exit condition. */
95 wake_up(&pvr2_context_sync_data);
97 mutex_unlock(&pvr2_context_mutex);
98 kfree(mp);
102 static void pvr2_context_notify(struct pvr2_context *mp)
104 pvr2_context_set_notify(mp,!0);
108 static void pvr2_context_check(struct pvr2_context *mp)
110 struct pvr2_channel *ch1, *ch2;
111 pvr2_trace(PVR2_TRACE_CTXT,
112 "pvr2_context %p (notify)", mp);
113 if (!mp->initialized_flag && !mp->disconnect_flag) {
114 mp->initialized_flag = !0;
115 pvr2_trace(PVR2_TRACE_CTXT,
116 "pvr2_context %p (initialize)", mp);
117 /* Finish hardware initialization */
118 if (pvr2_hdw_initialize(mp->hdw,
119 (void (*)(void *))pvr2_context_notify,
120 mp)) {
121 mp->video_stream.stream =
122 pvr2_hdw_get_video_stream(mp->hdw);
123 /* Trigger interface initialization. By doing this
124 here initialization runs in our own safe and
125 cozy thread context. */
126 if (mp->setup_func) mp->setup_func(mp);
127 } else {
128 pvr2_trace(PVR2_TRACE_CTXT,
129 "pvr2_context %p (thread skipping setup)",
130 mp);
131 /* Even though initialization did not succeed,
132 we're still going to continue anyway. We need
133 to do this in order to await the expected
134 disconnect (which we will detect in the normal
135 course of operation). */
139 for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
140 ch2 = ch1->mc_next;
141 if (ch1->check_func) ch1->check_func(ch1);
144 if (mp->disconnect_flag && !mp->mc_first) {
145 /* Go away... */
146 pvr2_context_destroy(mp);
147 return;
152 static int pvr2_context_shutok(void)
154 return pvr2_context_cleanup_flag && (pvr2_context_exist_first == NULL);
158 static int pvr2_context_thread_func(void *foo)
160 struct pvr2_context *mp;
162 pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread start");
164 do {
165 while ((mp = pvr2_context_notify_first) != NULL) {
166 pvr2_context_set_notify(mp, 0);
167 pvr2_context_check(mp);
169 wait_event_interruptible(
170 pvr2_context_sync_data,
171 ((pvr2_context_notify_first != NULL) ||
172 pvr2_context_shutok()));
173 } while (!pvr2_context_shutok());
175 pvr2_context_cleaned_flag = !0;
176 wake_up(&pvr2_context_cleanup_data);
178 pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread cleaned up");
180 wait_event_interruptible(
181 pvr2_context_sync_data,
182 kthread_should_stop());
184 pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end");
186 return 0;
190 int pvr2_context_global_init(void)
192 pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func,
193 NULL,
194 "pvrusb2-context");
195 return IS_ERR(pvr2_context_thread_ptr) ? -ENOMEM : 0;
199 void pvr2_context_global_done(void)
201 pvr2_context_cleanup_flag = !0;
202 wake_up(&pvr2_context_sync_data);
203 wait_event_interruptible(
204 pvr2_context_cleanup_data,
205 pvr2_context_cleaned_flag);
206 kthread_stop(pvr2_context_thread_ptr);
210 struct pvr2_context *pvr2_context_create(
211 struct usb_interface *intf,
212 const struct usb_device_id *devid,
213 void (*setup_func)(struct pvr2_context *))
215 struct pvr2_context *mp = NULL;
216 mp = kzalloc(sizeof(*mp),GFP_KERNEL);
217 if (!mp) goto done;
218 pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp);
219 mp->setup_func = setup_func;
220 mutex_init(&mp->mutex);
221 mutex_lock(&pvr2_context_mutex);
222 mp->exist_prev = pvr2_context_exist_last;
223 mp->exist_next = NULL;
224 pvr2_context_exist_last = mp;
225 if (mp->exist_prev) {
226 mp->exist_prev->exist_next = mp;
227 } else {
228 pvr2_context_exist_first = mp;
230 mutex_unlock(&pvr2_context_mutex);
231 mp->hdw = pvr2_hdw_create(intf,devid);
232 if (!mp->hdw) {
233 pvr2_context_destroy(mp);
234 mp = NULL;
235 goto done;
237 pvr2_context_set_notify(mp, !0);
238 done:
239 return mp;
243 static void pvr2_context_reset_input_limits(struct pvr2_context *mp)
245 unsigned int tmsk,mmsk;
246 struct pvr2_channel *cp;
247 struct pvr2_hdw *hdw = mp->hdw;
248 mmsk = pvr2_hdw_get_input_available(hdw);
249 tmsk = mmsk;
250 for (cp = mp->mc_first; cp; cp = cp->mc_next) {
251 if (!cp->input_mask) continue;
252 tmsk &= cp->input_mask;
254 pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk);
255 pvr2_hdw_commit_ctl(hdw);
259 static void pvr2_context_enter(struct pvr2_context *mp)
261 mutex_lock(&mp->mutex);
265 static void pvr2_context_exit(struct pvr2_context *mp)
267 int destroy_flag = 0;
268 if (!(mp->mc_first || !mp->disconnect_flag)) {
269 destroy_flag = !0;
271 mutex_unlock(&mp->mutex);
272 if (destroy_flag) pvr2_context_notify(mp);
276 void pvr2_context_disconnect(struct pvr2_context *mp)
278 pvr2_hdw_disconnect(mp->hdw);
279 mp->disconnect_flag = !0;
280 pvr2_context_notify(mp);
284 void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
286 pvr2_context_enter(mp);
287 cp->hdw = mp->hdw;
288 cp->mc_head = mp;
289 cp->mc_next = NULL;
290 cp->mc_prev = mp->mc_last;
291 if (mp->mc_last) {
292 mp->mc_last->mc_next = cp;
293 } else {
294 mp->mc_first = cp;
296 mp->mc_last = cp;
297 pvr2_context_exit(mp);
301 static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
303 if (!cp->stream) return;
304 pvr2_stream_kill(cp->stream->stream);
305 cp->stream->user = NULL;
306 cp->stream = NULL;
310 void pvr2_channel_done(struct pvr2_channel *cp)
312 struct pvr2_context *mp = cp->mc_head;
313 pvr2_context_enter(mp);
314 cp->input_mask = 0;
315 pvr2_channel_disclaim_stream(cp);
316 pvr2_context_reset_input_limits(mp);
317 if (cp->mc_next) {
318 cp->mc_next->mc_prev = cp->mc_prev;
319 } else {
320 mp->mc_last = cp->mc_prev;
322 if (cp->mc_prev) {
323 cp->mc_prev->mc_next = cp->mc_next;
324 } else {
325 mp->mc_first = cp->mc_next;
327 cp->hdw = NULL;
328 pvr2_context_exit(mp);
332 int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk)
334 unsigned int tmsk,mmsk;
335 int ret = 0;
336 struct pvr2_channel *p2;
337 struct pvr2_hdw *hdw = cp->hdw;
339 mmsk = pvr2_hdw_get_input_available(hdw);
340 cmsk &= mmsk;
341 if (cmsk == cp->input_mask) {
342 /* No change; nothing to do */
343 return 0;
346 pvr2_context_enter(cp->mc_head);
347 do {
348 if (!cmsk) {
349 cp->input_mask = 0;
350 pvr2_context_reset_input_limits(cp->mc_head);
351 break;
353 tmsk = mmsk;
354 for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) {
355 if (p2 == cp) continue;
356 if (!p2->input_mask) continue;
357 tmsk &= p2->input_mask;
359 if (!(tmsk & cmsk)) {
360 ret = -EPERM;
361 break;
363 tmsk &= cmsk;
364 if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) {
365 /* Internal failure changing allowed list; probably
366 should not happen, but react if it does. */
367 break;
369 cp->input_mask = cmsk;
370 pvr2_hdw_commit_ctl(hdw);
371 } while (0);
372 pvr2_context_exit(cp->mc_head);
373 return ret;
377 unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp)
379 return cp->input_mask;
383 int pvr2_channel_claim_stream(struct pvr2_channel *cp,
384 struct pvr2_context_stream *sp)
386 int code = 0;
387 pvr2_context_enter(cp->mc_head); do {
388 if (sp == cp->stream) break;
389 if (sp && sp->user) {
390 code = -EBUSY;
391 break;
393 pvr2_channel_disclaim_stream(cp);
394 if (!sp) break;
395 sp->user = cp;
396 cp->stream = sp;
397 } while (0);
398 pvr2_context_exit(cp->mc_head);
399 return code;
403 // This is the marker for the real beginning of a legitimate mpeg2 stream.
404 static char stream_sync_key[] = {
405 0x00, 0x00, 0x01, 0xba,
408 struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
409 struct pvr2_context_stream *sp)
411 struct pvr2_ioread *cp;
412 cp = pvr2_ioread_create();
413 if (!cp) return NULL;
414 pvr2_ioread_setup(cp,sp->stream);
415 pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key));
416 return cp;