1  // SPDX-License-Identifier: GPL-2.0-only
2  /*
3   *
4   *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
5   */
6  
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>
17  
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;
28  
29  
pvr2_context_set_notify(struct pvr2_context * mp,int fl)30  static void pvr2_context_set_notify(struct pvr2_context *mp, int fl)
31  {
32  	int signal_flag = 0;
33  	mutex_lock(&pvr2_context_mutex);
34  	if (fl) {
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;
42  			} else {
43  				pvr2_context_notify_first = mp;
44  			}
45  			mp->notify_flag = !0;
46  		}
47  	} else {
48  		if (mp->notify_flag) {
49  			mp->notify_flag = 0;
50  			if (mp->notify_next) {
51  				mp->notify_next->notify_prev = mp->notify_prev;
52  			} else {
53  				pvr2_context_notify_last = mp->notify_prev;
54  			}
55  			if (mp->notify_prev) {
56  				mp->notify_prev->notify_next = mp->notify_next;
57  			} else {
58  				pvr2_context_notify_first = mp->notify_next;
59  			}
60  		}
61  	}
62  	mutex_unlock(&pvr2_context_mutex);
63  	if (signal_flag) wake_up(&pvr2_context_sync_data);
64  }
65  
66  
pvr2_context_destroy(struct pvr2_context * mp)67  static void pvr2_context_destroy(struct pvr2_context *mp)
68  {
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);
73  	if (mp->exist_next) {
74  		mp->exist_next->exist_prev = mp->exist_prev;
75  	} else {
76  		pvr2_context_exist_last = mp->exist_prev;
77  	}
78  	if (mp->exist_prev) {
79  		mp->exist_prev->exist_next = mp->exist_next;
80  	} else {
81  		pvr2_context_exist_first = mp->exist_next;
82  	}
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);
87  	}
88  	mutex_unlock(&pvr2_context_mutex);
89  	kfree(mp);
90  }
91  
92  
pvr2_context_notify(struct pvr2_context * mp)93  static void pvr2_context_notify(struct pvr2_context *mp)
94  {
95  	pvr2_context_set_notify(mp,!0);
96  }
97  
98  
pvr2_context_check(struct pvr2_context * mp)99  static void pvr2_context_check(struct pvr2_context *mp)
100  {
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,
111  					mp)) {
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);
118  		} else {
119  			pvr2_trace(PVR2_TRACE_CTXT,
120  				   "pvr2_context %p (thread skipping setup)",
121  				   mp);
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). */
127  		}
128  	}
129  
130  	for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
131  		ch2 = ch1->mc_next;
132  		if (ch1->check_func) ch1->check_func(ch1);
133  	}
134  
135  	if (mp->disconnect_flag && !mp->mc_first) {
136  		/* Go away... */
137  		pvr2_context_destroy(mp);
138  		return;
139  	}
140  }
141  
142  
pvr2_context_shutok(void)143  static int pvr2_context_shutok(void)
144  {
145  	return pvr2_context_cleanup_flag && (pvr2_context_exist_first == NULL);
146  }
147  
148  
pvr2_context_thread_func(void * foo)149  static int pvr2_context_thread_func(void *foo)
150  {
151  	struct pvr2_context *mp;
152  
153  	pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread start");
154  
155  	do {
156  		while ((mp = pvr2_context_notify_first) != NULL) {
157  			pvr2_context_set_notify(mp, 0);
158  			pvr2_context_check(mp);
159  		}
160  		wait_event_interruptible(
161  			pvr2_context_sync_data,
162  			((pvr2_context_notify_first != NULL) ||
163  			 pvr2_context_shutok()));
164  	} while (!pvr2_context_shutok());
165  
166  	pvr2_context_cleaned_flag = !0;
167  	wake_up(&pvr2_context_cleanup_data);
168  
169  	pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread cleaned up");
170  
171  	wait_event_interruptible(
172  		pvr2_context_sync_data,
173  		kthread_should_stop());
174  
175  	pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end");
176  
177  	return 0;
178  }
179  
180  
pvr2_context_global_init(void)181  int pvr2_context_global_init(void)
182  {
183  	pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func,
184  					      NULL,
185  					      "pvrusb2-context");
186  	return IS_ERR(pvr2_context_thread_ptr) ? -ENOMEM : 0;
187  }
188  
189  
pvr2_context_global_done(void)190  void pvr2_context_global_done(void)
191  {
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);
198  }
199  
200  
pvr2_context_create(struct usb_interface * intf,const struct usb_device_id * devid,void (* setup_func)(struct pvr2_context *))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 *))
205  {
206  	struct pvr2_context *mp = NULL;
207  	mp = kzalloc(sizeof(*mp),GFP_KERNEL);
208  	if (!mp) goto done;
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;
218  	} else {
219  		pvr2_context_exist_first = mp;
220  	}
221  	mutex_unlock(&pvr2_context_mutex);
222  	mp->hdw = pvr2_hdw_create(intf,devid);
223  	if (!mp->hdw) {
224  		pvr2_context_destroy(mp);
225  		mp = NULL;
226  		goto done;
227  	}
228  	pvr2_context_set_notify(mp, !0);
229   done:
230  	return mp;
231  }
232  
233  
pvr2_context_reset_input_limits(struct pvr2_context * mp)234  static void pvr2_context_reset_input_limits(struct pvr2_context *mp)
235  {
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);
240  	tmsk = mmsk;
241  	for (cp = mp->mc_first; cp; cp = cp->mc_next) {
242  		if (!cp->input_mask) continue;
243  		tmsk &= cp->input_mask;
244  	}
245  	pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk);
246  	pvr2_hdw_commit_ctl(hdw);
247  }
248  
249  
pvr2_context_enter(struct pvr2_context * mp)250  static void pvr2_context_enter(struct pvr2_context *mp)
251  {
252  	mutex_lock(&mp->mutex);
253  }
254  
255  
pvr2_context_exit(struct pvr2_context * mp)256  static void pvr2_context_exit(struct pvr2_context *mp)
257  {
258  	int destroy_flag = 0;
259  	if (!(mp->mc_first || !mp->disconnect_flag)) {
260  		destroy_flag = !0;
261  	}
262  	mutex_unlock(&mp->mutex);
263  	if (destroy_flag) pvr2_context_notify(mp);
264  }
265  
266  
pvr2_context_disconnect(struct pvr2_context * mp)267  void pvr2_context_disconnect(struct pvr2_context *mp)
268  {
269  	pvr2_hdw_disconnect(mp->hdw);
270  	mp->disconnect_flag = !0;
271  	pvr2_context_notify(mp);
272  }
273  
274  
pvr2_channel_init(struct pvr2_channel * cp,struct pvr2_context * mp)275  void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
276  {
277  	pvr2_context_enter(mp);
278  	cp->hdw = mp->hdw;
279  	cp->mc_head = mp;
280  	cp->mc_next = NULL;
281  	cp->mc_prev = mp->mc_last;
282  	if (mp->mc_last) {
283  		mp->mc_last->mc_next = cp;
284  	} else {
285  		mp->mc_first = cp;
286  	}
287  	mp->mc_last = cp;
288  	pvr2_context_exit(mp);
289  }
290  
291  
pvr2_channel_disclaim_stream(struct pvr2_channel * cp)292  static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
293  {
294  	if (!cp->stream) return;
295  	pvr2_stream_kill(cp->stream->stream);
296  	cp->stream->user = NULL;
297  	cp->stream = NULL;
298  }
299  
300  
pvr2_channel_done(struct pvr2_channel * cp)301  void pvr2_channel_done(struct pvr2_channel *cp)
302  {
303  	struct pvr2_context *mp = cp->mc_head;
304  	pvr2_context_enter(mp);
305  	cp->input_mask = 0;
306  	pvr2_channel_disclaim_stream(cp);
307  	pvr2_context_reset_input_limits(mp);
308  	if (cp->mc_next) {
309  		cp->mc_next->mc_prev = cp->mc_prev;
310  	} else {
311  		mp->mc_last = cp->mc_prev;
312  	}
313  	if (cp->mc_prev) {
314  		cp->mc_prev->mc_next = cp->mc_next;
315  	} else {
316  		mp->mc_first = cp->mc_next;
317  	}
318  	cp->hdw = NULL;
319  	pvr2_context_exit(mp);
320  }
321  
322  
pvr2_channel_limit_inputs(struct pvr2_channel * cp,unsigned int cmsk)323  int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk)
324  {
325  	unsigned int tmsk,mmsk;
326  	int ret = 0;
327  	struct pvr2_channel *p2;
328  	struct pvr2_hdw *hdw = cp->hdw;
329  
330  	mmsk = pvr2_hdw_get_input_available(hdw);
331  	cmsk &= mmsk;
332  	if (cmsk == cp->input_mask) {
333  		/* No change; nothing to do */
334  		return 0;
335  	}
336  
337  	pvr2_context_enter(cp->mc_head);
338  	do {
339  		if (!cmsk) {
340  			cp->input_mask = 0;
341  			pvr2_context_reset_input_limits(cp->mc_head);
342  			break;
343  		}
344  		tmsk = mmsk;
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;
349  		}
350  		if (!(tmsk & cmsk)) {
351  			ret = -EPERM;
352  			break;
353  		}
354  		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. */
358  			break;
359  		}
360  		cp->input_mask = cmsk;
361  		pvr2_hdw_commit_ctl(hdw);
362  	} while (0);
363  	pvr2_context_exit(cp->mc_head);
364  	return ret;
365  }
366  
367  
pvr2_channel_get_limited_inputs(struct pvr2_channel * cp)368  unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp)
369  {
370  	return cp->input_mask;
371  }
372  
373  
pvr2_channel_claim_stream(struct pvr2_channel * cp,struct pvr2_context_stream * sp)374  int pvr2_channel_claim_stream(struct pvr2_channel *cp,
375  			      struct pvr2_context_stream *sp)
376  {
377  	int code = 0;
378  	pvr2_context_enter(cp->mc_head); do {
379  		if (sp == cp->stream) break;
380  		if (sp && sp->user) {
381  			code = -EBUSY;
382  			break;
383  		}
384  		pvr2_channel_disclaim_stream(cp);
385  		if (!sp) break;
386  		sp->user = cp;
387  		cp->stream = sp;
388  	} while (0);
389  	pvr2_context_exit(cp->mc_head);
390  	return code;
391  }
392  
393  
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,
397  };
398  
pvr2_channel_create_mpeg_stream(struct pvr2_context_stream * sp)399  struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
400  	struct pvr2_context_stream *sp)
401  {
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));
407  	return cp;
408  }
409