162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2005 Mike Isely <isely@pobox.com> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include "pvrusb2-context.h" 862306a36Sopenharmony_ci#include "pvrusb2-io.h" 962306a36Sopenharmony_ci#include "pvrusb2-ioread.h" 1062306a36Sopenharmony_ci#include "pvrusb2-hdw.h" 1162306a36Sopenharmony_ci#include "pvrusb2-debug.h" 1262306a36Sopenharmony_ci#include <linux/wait.h> 1362306a36Sopenharmony_ci#include <linux/kthread.h> 1462306a36Sopenharmony_ci#include <linux/errno.h> 1562306a36Sopenharmony_ci#include <linux/string.h> 1662306a36Sopenharmony_ci#include <linux/slab.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic struct pvr2_context *pvr2_context_exist_first; 1962306a36Sopenharmony_cistatic struct pvr2_context *pvr2_context_exist_last; 2062306a36Sopenharmony_cistatic struct pvr2_context *pvr2_context_notify_first; 2162306a36Sopenharmony_cistatic struct pvr2_context *pvr2_context_notify_last; 2262306a36Sopenharmony_cistatic DEFINE_MUTEX(pvr2_context_mutex); 2362306a36Sopenharmony_cistatic DECLARE_WAIT_QUEUE_HEAD(pvr2_context_sync_data); 2462306a36Sopenharmony_cistatic DECLARE_WAIT_QUEUE_HEAD(pvr2_context_cleanup_data); 2562306a36Sopenharmony_cistatic int pvr2_context_cleanup_flag; 2662306a36Sopenharmony_cistatic int pvr2_context_cleaned_flag; 2762306a36Sopenharmony_cistatic struct task_struct *pvr2_context_thread_ptr; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic void pvr2_context_set_notify(struct pvr2_context *mp, int fl) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci int signal_flag = 0; 3362306a36Sopenharmony_ci mutex_lock(&pvr2_context_mutex); 3462306a36Sopenharmony_ci if (fl) { 3562306a36Sopenharmony_ci if (!mp->notify_flag) { 3662306a36Sopenharmony_ci signal_flag = (pvr2_context_notify_first == NULL); 3762306a36Sopenharmony_ci mp->notify_prev = pvr2_context_notify_last; 3862306a36Sopenharmony_ci mp->notify_next = NULL; 3962306a36Sopenharmony_ci pvr2_context_notify_last = mp; 4062306a36Sopenharmony_ci if (mp->notify_prev) { 4162306a36Sopenharmony_ci mp->notify_prev->notify_next = mp; 4262306a36Sopenharmony_ci } else { 4362306a36Sopenharmony_ci pvr2_context_notify_first = mp; 4462306a36Sopenharmony_ci } 4562306a36Sopenharmony_ci mp->notify_flag = !0; 4662306a36Sopenharmony_ci } 4762306a36Sopenharmony_ci } else { 4862306a36Sopenharmony_ci if (mp->notify_flag) { 4962306a36Sopenharmony_ci mp->notify_flag = 0; 5062306a36Sopenharmony_ci if (mp->notify_next) { 5162306a36Sopenharmony_ci mp->notify_next->notify_prev = mp->notify_prev; 5262306a36Sopenharmony_ci } else { 5362306a36Sopenharmony_ci pvr2_context_notify_last = mp->notify_prev; 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci if (mp->notify_prev) { 5662306a36Sopenharmony_ci mp->notify_prev->notify_next = mp->notify_next; 5762306a36Sopenharmony_ci } else { 5862306a36Sopenharmony_ci pvr2_context_notify_first = mp->notify_next; 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci } 6262306a36Sopenharmony_ci mutex_unlock(&pvr2_context_mutex); 6362306a36Sopenharmony_ci if (signal_flag) wake_up(&pvr2_context_sync_data); 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic void pvr2_context_destroy(struct pvr2_context *mp) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp); 7062306a36Sopenharmony_ci pvr2_hdw_destroy(mp->hdw); 7162306a36Sopenharmony_ci pvr2_context_set_notify(mp, 0); 7262306a36Sopenharmony_ci mutex_lock(&pvr2_context_mutex); 7362306a36Sopenharmony_ci if (mp->exist_next) { 7462306a36Sopenharmony_ci mp->exist_next->exist_prev = mp->exist_prev; 7562306a36Sopenharmony_ci } else { 7662306a36Sopenharmony_ci pvr2_context_exist_last = mp->exist_prev; 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci if (mp->exist_prev) { 7962306a36Sopenharmony_ci mp->exist_prev->exist_next = mp->exist_next; 8062306a36Sopenharmony_ci } else { 8162306a36Sopenharmony_ci pvr2_context_exist_first = mp->exist_next; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci if (!pvr2_context_exist_first) { 8462306a36Sopenharmony_ci /* Trigger wakeup on control thread in case it is waiting 8562306a36Sopenharmony_ci for an exit condition. */ 8662306a36Sopenharmony_ci wake_up(&pvr2_context_sync_data); 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci mutex_unlock(&pvr2_context_mutex); 8962306a36Sopenharmony_ci kfree(mp); 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic void pvr2_context_notify(void *ptr) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci struct pvr2_context *mp = ptr; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci pvr2_context_set_notify(mp,!0); 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic void pvr2_context_check(struct pvr2_context *mp) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci struct pvr2_channel *ch1, *ch2; 10462306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_CTXT, 10562306a36Sopenharmony_ci "pvr2_context %p (notify)", mp); 10662306a36Sopenharmony_ci if (!mp->initialized_flag && !mp->disconnect_flag) { 10762306a36Sopenharmony_ci mp->initialized_flag = !0; 10862306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_CTXT, 10962306a36Sopenharmony_ci "pvr2_context %p (initialize)", mp); 11062306a36Sopenharmony_ci /* Finish hardware initialization */ 11162306a36Sopenharmony_ci if (pvr2_hdw_initialize(mp->hdw, pvr2_context_notify, mp)) { 11262306a36Sopenharmony_ci mp->video_stream.stream = 11362306a36Sopenharmony_ci pvr2_hdw_get_video_stream(mp->hdw); 11462306a36Sopenharmony_ci /* Trigger interface initialization. By doing this 11562306a36Sopenharmony_ci here initialization runs in our own safe and 11662306a36Sopenharmony_ci cozy thread context. */ 11762306a36Sopenharmony_ci if (mp->setup_func) mp->setup_func(mp); 11862306a36Sopenharmony_ci } else { 11962306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_CTXT, 12062306a36Sopenharmony_ci "pvr2_context %p (thread skipping setup)", 12162306a36Sopenharmony_ci mp); 12262306a36Sopenharmony_ci /* Even though initialization did not succeed, 12362306a36Sopenharmony_ci we're still going to continue anyway. We need 12462306a36Sopenharmony_ci to do this in order to await the expected 12562306a36Sopenharmony_ci disconnect (which we will detect in the normal 12662306a36Sopenharmony_ci course of operation). */ 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci for (ch1 = mp->mc_first; ch1; ch1 = ch2) { 13162306a36Sopenharmony_ci ch2 = ch1->mc_next; 13262306a36Sopenharmony_ci if (ch1->check_func) ch1->check_func(ch1); 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci if (mp->disconnect_flag && !mp->mc_first) { 13662306a36Sopenharmony_ci /* Go away... */ 13762306a36Sopenharmony_ci pvr2_context_destroy(mp); 13862306a36Sopenharmony_ci return; 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic int pvr2_context_shutok(void) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci return pvr2_context_cleanup_flag && (pvr2_context_exist_first == NULL); 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic int pvr2_context_thread_func(void *foo) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci struct pvr2_context *mp; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread start"); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci do { 15662306a36Sopenharmony_ci while ((mp = pvr2_context_notify_first) != NULL) { 15762306a36Sopenharmony_ci pvr2_context_set_notify(mp, 0); 15862306a36Sopenharmony_ci pvr2_context_check(mp); 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci wait_event_interruptible( 16162306a36Sopenharmony_ci pvr2_context_sync_data, 16262306a36Sopenharmony_ci ((pvr2_context_notify_first != NULL) || 16362306a36Sopenharmony_ci pvr2_context_shutok())); 16462306a36Sopenharmony_ci } while (!pvr2_context_shutok()); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci pvr2_context_cleaned_flag = !0; 16762306a36Sopenharmony_ci wake_up(&pvr2_context_cleanup_data); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread cleaned up"); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci wait_event_interruptible( 17262306a36Sopenharmony_ci pvr2_context_sync_data, 17362306a36Sopenharmony_ci kthread_should_stop()); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end"); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci return 0; 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ciint pvr2_context_global_init(void) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func, 18462306a36Sopenharmony_ci NULL, 18562306a36Sopenharmony_ci "pvrusb2-context"); 18662306a36Sopenharmony_ci return IS_ERR(pvr2_context_thread_ptr) ? -ENOMEM : 0; 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_civoid pvr2_context_global_done(void) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci pvr2_context_cleanup_flag = !0; 19362306a36Sopenharmony_ci wake_up(&pvr2_context_sync_data); 19462306a36Sopenharmony_ci wait_event_interruptible( 19562306a36Sopenharmony_ci pvr2_context_cleanup_data, 19662306a36Sopenharmony_ci pvr2_context_cleaned_flag); 19762306a36Sopenharmony_ci kthread_stop(pvr2_context_thread_ptr); 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cistruct pvr2_context *pvr2_context_create( 20262306a36Sopenharmony_ci struct usb_interface *intf, 20362306a36Sopenharmony_ci const struct usb_device_id *devid, 20462306a36Sopenharmony_ci void (*setup_func)(struct pvr2_context *)) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci struct pvr2_context *mp = NULL; 20762306a36Sopenharmony_ci mp = kzalloc(sizeof(*mp),GFP_KERNEL); 20862306a36Sopenharmony_ci if (!mp) goto done; 20962306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp); 21062306a36Sopenharmony_ci mp->setup_func = setup_func; 21162306a36Sopenharmony_ci mutex_init(&mp->mutex); 21262306a36Sopenharmony_ci mutex_lock(&pvr2_context_mutex); 21362306a36Sopenharmony_ci mp->exist_prev = pvr2_context_exist_last; 21462306a36Sopenharmony_ci mp->exist_next = NULL; 21562306a36Sopenharmony_ci pvr2_context_exist_last = mp; 21662306a36Sopenharmony_ci if (mp->exist_prev) { 21762306a36Sopenharmony_ci mp->exist_prev->exist_next = mp; 21862306a36Sopenharmony_ci } else { 21962306a36Sopenharmony_ci pvr2_context_exist_first = mp; 22062306a36Sopenharmony_ci } 22162306a36Sopenharmony_ci mutex_unlock(&pvr2_context_mutex); 22262306a36Sopenharmony_ci mp->hdw = pvr2_hdw_create(intf,devid); 22362306a36Sopenharmony_ci if (!mp->hdw) { 22462306a36Sopenharmony_ci pvr2_context_destroy(mp); 22562306a36Sopenharmony_ci mp = NULL; 22662306a36Sopenharmony_ci goto done; 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci pvr2_context_set_notify(mp, !0); 22962306a36Sopenharmony_ci done: 23062306a36Sopenharmony_ci return mp; 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic void pvr2_context_reset_input_limits(struct pvr2_context *mp) 23562306a36Sopenharmony_ci{ 23662306a36Sopenharmony_ci unsigned int tmsk,mmsk; 23762306a36Sopenharmony_ci struct pvr2_channel *cp; 23862306a36Sopenharmony_ci struct pvr2_hdw *hdw = mp->hdw; 23962306a36Sopenharmony_ci mmsk = pvr2_hdw_get_input_available(hdw); 24062306a36Sopenharmony_ci tmsk = mmsk; 24162306a36Sopenharmony_ci for (cp = mp->mc_first; cp; cp = cp->mc_next) { 24262306a36Sopenharmony_ci if (!cp->input_mask) continue; 24362306a36Sopenharmony_ci tmsk &= cp->input_mask; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk); 24662306a36Sopenharmony_ci pvr2_hdw_commit_ctl(hdw); 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic void pvr2_context_enter(struct pvr2_context *mp) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci mutex_lock(&mp->mutex); 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic void pvr2_context_exit(struct pvr2_context *mp) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci int destroy_flag = 0; 25962306a36Sopenharmony_ci if (!(mp->mc_first || !mp->disconnect_flag)) { 26062306a36Sopenharmony_ci destroy_flag = !0; 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci mutex_unlock(&mp->mutex); 26362306a36Sopenharmony_ci if (destroy_flag) pvr2_context_notify(mp); 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_civoid pvr2_context_disconnect(struct pvr2_context *mp) 26862306a36Sopenharmony_ci{ 26962306a36Sopenharmony_ci pvr2_hdw_disconnect(mp->hdw); 27062306a36Sopenharmony_ci if (!pvr2_context_shutok()) 27162306a36Sopenharmony_ci pvr2_context_notify(mp); 27262306a36Sopenharmony_ci mp->disconnect_flag = !0; 27362306a36Sopenharmony_ci} 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_civoid pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci pvr2_context_enter(mp); 27962306a36Sopenharmony_ci cp->hdw = mp->hdw; 28062306a36Sopenharmony_ci cp->mc_head = mp; 28162306a36Sopenharmony_ci cp->mc_next = NULL; 28262306a36Sopenharmony_ci cp->mc_prev = mp->mc_last; 28362306a36Sopenharmony_ci if (mp->mc_last) { 28462306a36Sopenharmony_ci mp->mc_last->mc_next = cp; 28562306a36Sopenharmony_ci } else { 28662306a36Sopenharmony_ci mp->mc_first = cp; 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci mp->mc_last = cp; 28962306a36Sopenharmony_ci pvr2_context_exit(mp); 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic void pvr2_channel_disclaim_stream(struct pvr2_channel *cp) 29462306a36Sopenharmony_ci{ 29562306a36Sopenharmony_ci if (!cp->stream) return; 29662306a36Sopenharmony_ci pvr2_stream_kill(cp->stream->stream); 29762306a36Sopenharmony_ci cp->stream->user = NULL; 29862306a36Sopenharmony_ci cp->stream = NULL; 29962306a36Sopenharmony_ci} 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_civoid pvr2_channel_done(struct pvr2_channel *cp) 30362306a36Sopenharmony_ci{ 30462306a36Sopenharmony_ci struct pvr2_context *mp = cp->mc_head; 30562306a36Sopenharmony_ci pvr2_context_enter(mp); 30662306a36Sopenharmony_ci cp->input_mask = 0; 30762306a36Sopenharmony_ci pvr2_channel_disclaim_stream(cp); 30862306a36Sopenharmony_ci pvr2_context_reset_input_limits(mp); 30962306a36Sopenharmony_ci if (cp->mc_next) { 31062306a36Sopenharmony_ci cp->mc_next->mc_prev = cp->mc_prev; 31162306a36Sopenharmony_ci } else { 31262306a36Sopenharmony_ci mp->mc_last = cp->mc_prev; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci if (cp->mc_prev) { 31562306a36Sopenharmony_ci cp->mc_prev->mc_next = cp->mc_next; 31662306a36Sopenharmony_ci } else { 31762306a36Sopenharmony_ci mp->mc_first = cp->mc_next; 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci cp->hdw = NULL; 32062306a36Sopenharmony_ci pvr2_context_exit(mp); 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ciint pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk) 32562306a36Sopenharmony_ci{ 32662306a36Sopenharmony_ci unsigned int tmsk,mmsk; 32762306a36Sopenharmony_ci int ret = 0; 32862306a36Sopenharmony_ci struct pvr2_channel *p2; 32962306a36Sopenharmony_ci struct pvr2_hdw *hdw = cp->hdw; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci mmsk = pvr2_hdw_get_input_available(hdw); 33262306a36Sopenharmony_ci cmsk &= mmsk; 33362306a36Sopenharmony_ci if (cmsk == cp->input_mask) { 33462306a36Sopenharmony_ci /* No change; nothing to do */ 33562306a36Sopenharmony_ci return 0; 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci pvr2_context_enter(cp->mc_head); 33962306a36Sopenharmony_ci do { 34062306a36Sopenharmony_ci if (!cmsk) { 34162306a36Sopenharmony_ci cp->input_mask = 0; 34262306a36Sopenharmony_ci pvr2_context_reset_input_limits(cp->mc_head); 34362306a36Sopenharmony_ci break; 34462306a36Sopenharmony_ci } 34562306a36Sopenharmony_ci tmsk = mmsk; 34662306a36Sopenharmony_ci for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) { 34762306a36Sopenharmony_ci if (p2 == cp) continue; 34862306a36Sopenharmony_ci if (!p2->input_mask) continue; 34962306a36Sopenharmony_ci tmsk &= p2->input_mask; 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci if (!(tmsk & cmsk)) { 35262306a36Sopenharmony_ci ret = -EPERM; 35362306a36Sopenharmony_ci break; 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci tmsk &= cmsk; 35662306a36Sopenharmony_ci if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) { 35762306a36Sopenharmony_ci /* Internal failure changing allowed list; probably 35862306a36Sopenharmony_ci should not happen, but react if it does. */ 35962306a36Sopenharmony_ci break; 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci cp->input_mask = cmsk; 36262306a36Sopenharmony_ci pvr2_hdw_commit_ctl(hdw); 36362306a36Sopenharmony_ci } while (0); 36462306a36Sopenharmony_ci pvr2_context_exit(cp->mc_head); 36562306a36Sopenharmony_ci return ret; 36662306a36Sopenharmony_ci} 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ciunsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci return cp->input_mask; 37262306a36Sopenharmony_ci} 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ciint pvr2_channel_claim_stream(struct pvr2_channel *cp, 37662306a36Sopenharmony_ci struct pvr2_context_stream *sp) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci int code = 0; 37962306a36Sopenharmony_ci pvr2_context_enter(cp->mc_head); do { 38062306a36Sopenharmony_ci if (sp == cp->stream) break; 38162306a36Sopenharmony_ci if (sp && sp->user) { 38262306a36Sopenharmony_ci code = -EBUSY; 38362306a36Sopenharmony_ci break; 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci pvr2_channel_disclaim_stream(cp); 38662306a36Sopenharmony_ci if (!sp) break; 38762306a36Sopenharmony_ci sp->user = cp; 38862306a36Sopenharmony_ci cp->stream = sp; 38962306a36Sopenharmony_ci } while (0); 39062306a36Sopenharmony_ci pvr2_context_exit(cp->mc_head); 39162306a36Sopenharmony_ci return code; 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci// This is the marker for the real beginning of a legitimate mpeg2 stream. 39662306a36Sopenharmony_cistatic char stream_sync_key[] = { 39762306a36Sopenharmony_ci 0x00, 0x00, 0x01, 0xba, 39862306a36Sopenharmony_ci}; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_cistruct pvr2_ioread *pvr2_channel_create_mpeg_stream( 40162306a36Sopenharmony_ci struct pvr2_context_stream *sp) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci struct pvr2_ioread *cp; 40462306a36Sopenharmony_ci cp = pvr2_ioread_create(); 40562306a36Sopenharmony_ci if (!cp) return NULL; 40662306a36Sopenharmony_ci pvr2_ioread_setup(cp,sp->stream); 40762306a36Sopenharmony_ci pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key)); 40862306a36Sopenharmony_ci return cp; 40962306a36Sopenharmony_ci} 410