diff options
author | Mike Isely <isely@pobox.com> | 2008-04-21 02:47:43 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-24 13:09:49 -0400 |
commit | 1cb03b76d09d20accfa5c1664c16ba6566f539a0 (patch) | |
tree | 8c58f23151ab54f71472b80f6d0d29df25ddbb9f /drivers/media/video/pvrusb2/pvrusb2-context.c | |
parent | d3f8d8fb304a8b9a81eae16ff7b50f5379f2437e (diff) |
V4L/DVB (7719): pvrusb2: Implement input selection enforcement
In the pvrusb2 driver, different interfaces (e.g. V4L, DVB) have
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-context.c')
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-context.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c index a2ce022c515a..b5db6a5bab31 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/drivers/media/video/pvrusb2/pvrusb2-context.c | |||
@@ -245,6 +245,22 @@ struct pvr2_context *pvr2_context_create( | |||
245 | } | 245 | } |
246 | 246 | ||
247 | 247 | ||
248 | static void pvr2_context_reset_input_limits(struct pvr2_context *mp) | ||
249 | { | ||
250 | unsigned int tmsk,mmsk; | ||
251 | struct pvr2_channel *cp; | ||
252 | struct pvr2_hdw *hdw = mp->hdw; | ||
253 | mmsk = pvr2_hdw_get_input_available(hdw); | ||
254 | tmsk = mmsk; | ||
255 | for (cp = mp->mc_first; cp; cp = cp->mc_next) { | ||
256 | if (!cp->input_mask) continue; | ||
257 | tmsk &= cp->input_mask; | ||
258 | } | ||
259 | pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk); | ||
260 | pvr2_hdw_commit_ctl(hdw); | ||
261 | } | ||
262 | |||
263 | |||
248 | static void pvr2_context_enter(struct pvr2_context *mp) | 264 | static void pvr2_context_enter(struct pvr2_context *mp) |
249 | { | 265 | { |
250 | mutex_lock(&mp->mutex); | 266 | mutex_lock(&mp->mutex); |
@@ -300,7 +316,9 @@ void pvr2_channel_done(struct pvr2_channel *cp) | |||
300 | { | 316 | { |
301 | struct pvr2_context *mp = cp->mc_head; | 317 | struct pvr2_context *mp = cp->mc_head; |
302 | pvr2_context_enter(mp); | 318 | pvr2_context_enter(mp); |
319 | cp->input_mask = 0; | ||
303 | pvr2_channel_disclaim_stream(cp); | 320 | pvr2_channel_disclaim_stream(cp); |
321 | pvr2_context_reset_input_limits(mp); | ||
304 | if (cp->mc_next) { | 322 | if (cp->mc_next) { |
305 | cp->mc_next->mc_prev = cp->mc_prev; | 323 | cp->mc_next->mc_prev = cp->mc_prev; |
306 | } else { | 324 | } else { |
@@ -316,6 +334,57 @@ void pvr2_channel_done(struct pvr2_channel *cp) | |||
316 | } | 334 | } |
317 | 335 | ||
318 | 336 | ||
337 | int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk) | ||
338 | { | ||
339 | unsigned int tmsk,mmsk; | ||
340 | int ret = 0; | ||
341 | struct pvr2_channel *p2; | ||
342 | struct pvr2_hdw *hdw = cp->hdw; | ||
343 | |||
344 | mmsk = pvr2_hdw_get_input_available(hdw); | ||
345 | cmsk &= mmsk; | ||
346 | if (cmsk == cp->input_mask) { | ||
347 | /* No change; nothing to do */ | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | pvr2_context_enter(cp->mc_head); | ||
352 | do { | ||
353 | if (!cmsk) { | ||
354 | cp->input_mask = 0; | ||
355 | pvr2_context_reset_input_limits(cp->mc_head); | ||
356 | break; | ||
357 | } | ||
358 | tmsk = mmsk; | ||
359 | for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) { | ||
360 | if (p2 == cp) continue; | ||
361 | if (!p2->input_mask) continue; | ||
362 | tmsk &= p2->input_mask; | ||
363 | } | ||
364 | if (!(tmsk & cmsk)) { | ||
365 | ret = -EPERM; | ||
366 | break; | ||
367 | } | ||
368 | tmsk &= cmsk; | ||
369 | if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) { | ||
370 | /* Internal failure changing allowed list; probably | ||
371 | should not happen, but react if it does. */ | ||
372 | break; | ||
373 | } | ||
374 | cp->input_mask = cmsk; | ||
375 | pvr2_hdw_commit_ctl(hdw); | ||
376 | } while (0); | ||
377 | pvr2_context_exit(cp->mc_head); | ||
378 | return ret; | ||
379 | } | ||
380 | |||
381 | |||
382 | unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp) | ||
383 | { | ||
384 | return cp->input_mask; | ||
385 | } | ||
386 | |||
387 | |||
319 | int pvr2_channel_claim_stream(struct pvr2_channel *cp, | 388 | int pvr2_channel_claim_stream(struct pvr2_channel *cp, |
320 | struct pvr2_context_stream *sp) | 389 | struct pvr2_context_stream *sp) |
321 | { | 390 | { |