📄 pvrusb2-hdw.c
字号:
} return 0;}/* Set the current value of a given control. This assumes we are already inside our critical region. */int pvr2_ctrl_internal_set_value(struct pvr2_ctrl *cptr,int value){ const struct pvr2_ctl_def *dptr; int ret; if (!cptr) return -EINVAL; if (!cptr->is_valid) return -EINVAL; dptr = cptr->ctl_def; if (!dptr->is_valid) return -EINVAL; if (value < dptr->min_value) return -EINVAL; if (value > dptr->max_value) return -EINVAL; if (dptr->set_func) { ret = dptr->set_func(cptr,value); pvr2_i2c_core_check_stale(cptr->hdw); pvr2_i2c_core_sync(cptr->hdw); return ret; } else if (dptr->get_func) { /* If there's no "set" function yet there is still a "get" function, then treat this as a read-only value. */ return -EINVAL; } if ((cptr->value != value) || (ctlchg != 0)) { cptr->value = value; cptr->dirty = !0; } return 0;}/* Get the current value of a given control. This assumes that we are already inside our critical region. */int pvr2_ctrl_internal_get_value(struct pvr2_ctrl *cptr){ const struct pvr2_ctl_def *dptr; if (!cptr) return 0; if (!cptr->is_valid) return 0; dptr = cptr->ctl_def; if (!dptr->is_valid) return 0; if (dptr->get_func) { return dptr->get_func(cptr); } return cptr->value;}/* Set the current value of the given control. */int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val){ int ret; if (!cptr) return -EINVAL; LOCK_TAKE(cptr->hdw->big_lock); do { ret = pvr2_ctrl_internal_set_value(cptr,val); } while(0); LOCK_GIVE(cptr->hdw->big_lock); return ret;}/* Get the current value of the given control. */int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr){ int ret; if (!cptr) return -EINVAL; LOCK_TAKE(cptr->hdw->big_lock); do { ret = pvr2_ctrl_internal_get_value(cptr); } while(0); LOCK_GIVE(cptr->hdw->big_lock); return ret;}/* Return the type of the given control (int, enum, or bit mask). */int pvr2_ctrl_get_type(struct pvr2_ctrl *cptr){ const struct pvr2_ctl_def *dptr; if (!cptr) return PVR2_CTRL_TYPE_INVALID; dptr = cptr->ctl_def; if (dptr->mask_value) { return PVR2_CTRL_TYPE_BITMASK; } if (dptr->value_defs_ptr) { return PVR2_CTRL_TYPE_ENUM; } return PVR2_CTRL_TYPE_INT;}/* Return the minimum legal value for a given control. This command is only relevant for int or enum types. */int pvr2_ctrl_get_min_value(struct pvr2_ctrl *cptr){ const struct pvr2_ctl_def *dptr; if (!cptr) return 0; dptr = cptr->ctl_def; return dptr->min_value;}/* Return the maximum legal value for a given control. This command is only relevant for int or enum types. */int pvr2_ctrl_get_max_value(struct pvr2_ctrl *cptr){ const struct pvr2_ctl_def *dptr; if (!cptr) return 0; dptr = cptr->ctl_def; return dptr->max_value;}/* Return the default value for a given control. */int pvr2_ctrl_get_default_value(struct pvr2_ctrl *cptr){ const struct pvr2_ctl_def *dptr; if (!cptr) return 0; dptr = cptr->ctl_def; return dptr->default_value;}/* Return a mask of which bits are used within the bit mask of a given control. This command is only relevant for bit mask types. */int pvr2_ctrl_get_mask_value(struct pvr2_ctrl *cptr){ const struct pvr2_ctl_def *dptr; if (!cptr) return 0; dptr = cptr->ctl_def; return dptr->mask_value;}/* Return true if this is a valid control. */int pvr2_ctrl_is_valid(struct pvr2_ctrl *cptr){ if (!cptr) return 0; return cptr->is_valid;}/* Return true if the control can be set (otherwise it may only be read, assuming that it is valid). */int pvr2_ctrl_is_writeable(struct pvr2_ctrl *cptr){ const struct pvr2_ctl_def *dptr; if (!cptr) return 0; dptr = cptr->ctl_def; if (!dptr->is_valid) return 0; if (dptr->set_func) return !0; if (dptr->get_func) return 0; return !0;}/* Return the control's name, or null if there isn't a name or the control isn't otherwise valid. */const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr){ const struct pvr2_ctl_def *dptr; if (!cptr) return 0; dptr = cptr->ctl_def; return dptr->name;}/* Return the control's description, or null if there isn't a name or the control isn't otherwise valid. */const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr){ const struct pvr2_ctl_def *dptr; if (!cptr) return 0; dptr = cptr->ctl_def; return dptr->desc;}/* Return the name for an enumeration value or bit mask position for the given control. If the control is not an enumeration or bit mask type, then return null. */const char *pvr2_ctrl_get_value_name(struct pvr2_ctrl *cptr,int val){ int msk,idx; const struct pvr2_ctl_def *dptr; if (!cptr) return 0; dptr = cptr->ctl_def; if (dptr->mask_value) { for (idx = 0, msk = 1; (idx < dptr->value_defs_count) && msk; idx++, msk <<= 1) { if (val & msk) { return dptr->value_defs_ptr[idx]; } } } else { val -= dptr->min_value; if (val < 0) return 0; if (val >= dptr->value_defs_count) return 0; return dptr->value_defs_ptr[val]; } return 0;}/* Commit all control changes made up to this point. Subsystems can be indirectly affected by these changes. For a given set of things being committed, we'll clear the affected subsystem bits and then once we're done committing everything we'll make a request to restore the subsystem state(s) back to their previous value before this function was called. Thus we can automatically reconfigure affected pieces of the driver as controls are changed. */int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw){ unsigned long saved_subsys_mask = hdw->subsys_enabled_mask; unsigned long stale_subsys_mask = 0; unsigned int idx; const struct pvr2_ctl_def *dptr; struct pvr2_ctrl *cptr; int value; const char *ctl_name; const char *ctl_value; int commit_flag = 0; /* Let's see if the channel changed and we have to update the frequency because of it. This setup means one can tune the receiver either by just setting the channel (using the frequency table), or by directly programming the frequency. How do we resolve the obvious conflict here? The direct frequency takes priority; if directly set then we commit that value and force the channel to zero which is interpreted to mean "none". If on the other hand we see that the channel has been set and it's a legal value, then we copy that into the frequency. The metaphor here is similar to when you tune your digital radio: You an either set a frequency directly or punch up a pre-programmed station. Either way a frequency is set, and if you do use a preset, then the radio also shows you which preset it is - until you override that by directly entering a new frequency. */ if (hdw->controls[PVR2_CID_FREQUENCY].dirty) { /* Frequency has been directly set, so clear out the channel. */ hdw->controls[PVR2_CID_CHANNEL].value = 0; } else if (hdw->controls[PVR2_CID_CHANNEL].dirty) { int id = hdw->controls[PVR2_CID_CHANNEL].value; if ((id > 0) && (id <= FREQTABLE_SIZE)) { if (hdw->controls[PVR2_CID_FREQUENCY].value != hdw->freqTable[id-1]) { hdw->controls[PVR2_CID_FREQUENCY].value = hdw->freqTable[id-1]; hdw->controls[PVR2_CID_FREQUENCY].dirty = !0; } } } for (idx = 0; idx < CTRL_COUNT; idx++) { cptr = hdw->controls + idx; if (!cptr->dirty) continue; if (!commit_flag) { commit_flag = !0; } value = cptr->value; dptr = cptr->ctl_def; ctl_name = dptr->name; if (dptr->value_defs_ptr) { if (value < dptr->value_defs_count) { ctl_value = dptr->value_defs_ptr[value]; } else { ctl_value = "<out of range>"; } } else { ctl_value = "<integer>"; } pvr2_trace(PVR2_TRACE_CTL, "/*--TRACE_COMMIT--*/ \"%s\" <-- %d (%s)", ctl_name,value,ctl_value); } if (!commit_flag) { /* Nothing has changed */ return 0; } /* When video standard changes, reset the hres and vres values - but if the user has pending changes there, then let the changes take priority. */ if (hdw->controls[PVR2_CID_STDCUR].dirty) { /* Rewrite the vertical resolution to be appropriate to the video standard that has been selected. */ int nvres; if (hdw->video_std_cur & V4L2_STD_525_60) { nvres = 480; } else { nvres = 576; } if (nvres != hdw->controls[PVR2_CID_VRES].value) { hdw->controls[PVR2_CID_VRES].value = nvres; hdw->controls[PVR2_CID_VRES].dirty = !0; } if (!hdw->controls[PVR2_CID_INTERLACE].value) { hdw->controls[PVR2_CID_INTERLACE].value = 0; hdw->controls[PVR2_CID_INTERLACE].dirty = !0; } } if (hdw->controls[PVR2_CID_STDCUR].dirty || hdw->controls[PVR2_CID_VRES].dirty || hdw->controls[PVR2_CID_HRES].dirty || hdw->controls[PVR2_CID_INTERLACE].dirty || hdw->controls[PVR2_CID_VBR].dirty || hdw->controls[PVR2_CID_AVERAGEVIDEOBITRATE].dirty || hdw->controls[PVR2_CID_PEAKVIDEOBITRATE].dirty || hdw->controls[PVR2_CID_AUDIOBITRATE].dirty || hdw->controls[PVR2_CID_SRATE].dirty || hdw->controls[PVR2_CID_AUDIOLAYER].dirty || hdw->controls[PVR2_CID_AUDIOCRC].dirty || hdw->controls[PVR2_CID_AUDIOEMPHASIS].dirty) { /* If any of this changes, then the encoder needs to be reconfigured, and we need to reset the stream. */ stale_subsys_mask |= PVR2_SUBSYS_ENC_CFG; stale_subsys_mask |= hdw->subsys_stream_mask; } /* Scan i2c core at this point - before we clear all the dirty bits. Various parts of the i2c core will notice dirty bits as appropriate and arrange to broadcast or directly send updates to the client drivers in order to keep everything in sync */ pvr2_i2c_core_check_stale(hdw); for (idx = 0; idx < CTRL_COUNT; idx++) { cptr = hdw->controls + idx; cptr->dirty = 0; } /* Now execute i2c core update */ pvr2_i2c_core_sync(hdw); pvr2_hdw_subsys_bit_chg_no_lock(hdw,stale_subsys_mask,0); pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,saved_subsys_mask); return 0;}int pvr2_hdw_commit_ctl(struct pvr2_hdw *hdw){ LOCK_TAKE(hdw->big_lock); do { pvr2_hdw_commit_ctl_internal(hdw); } while (0); LOCK_GIVE(hdw->big_lock); return 0;}void pvr2_hdw_poll(struct pvr2_hdw *hdw){ LOCK_TAKE(hdw->big_lock); do { pvr2_i2c_core_sync(hdw); } while (0); LOCK_GIVE(hdw->big_lock);}void pvr2_hdw_setup_poll_trigger(struct pvr2_hdw *hdw, void (*func)(void *), void *data){ LOCK_TAKE(hdw->big_lock); do { hdw->poll_trigger_func = func; hdw->poll_trigger_data = data; } while (0); LOCK_GIVE(hdw->big_lock);}void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *hdw){ if (hdw->poll_trigger_func) { hdw->poll_trigger_func(hdw->poll_trigger_data); }}void pvr2_hdw_poll_trigger(struct pvr2_hdw *hdw){ LOCK_TAKE(hdw->big_lock); do { pvr2_hdw_poll_trigger_unlocked(hdw); } while (0); LOCK_GIVE(hdw->big_lock);}/* Return name for this driver instance */const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw){ return hdw->name;}/* Return bit mask indicating signal status */unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw){ unsigned int msk = 0; switch (hdw->controls[PVR2_CID_INPUT].value) { case PVR2_CVAL_INPUT_TV: case PVR2_CVAL_INPUT_RADIO: if (hdw->decoder_ctrl && hdw->decoder_ctrl->tuned(hdw->decoder_ctrl->ctxt)) { msk |= PVR2_SIGNAL_OK; if (hdw->audio_stat && hdw->audio_stat->status(hdw->audio_stat->ctxt)) { if (hdw->flag_stereo) { msk |= PVR2_SIGNAL_STEREO; } if (hdw->flag_bilingual) { msk |= PVR2_SIGNAL_SAP; } } } break; default: msk |= PVR2_SIGNAL_OK | PVR2_SIGNAL_STEREO; } return msk;}static int pvr2_ctl_get_subsys_mask(struct pvr2_ctrl *cptr){ return cptr->hdw->subsys_enabled_mask;}static int pvr2_ctl_set_subsys_mask(struct pvr2_ctrl *cptr,int val){ pvr2_hdw_subsys_bit_chg_no_lock(cptr->hdw,~0,val); return 0;}static int pvr2_ctl_get_subsys_stream_mask(struct pvr2_ctrl *cptr){ return cptr->hdw->subsys_stream_mask;}static int pvr2_ctl_set_subsys_stream_mask(struct pvr2_ctrl *cptr, int val){ pvr2_hdw_subsys_stream_bit_chg_no_lock(cptr->hdw,~0,val); return 0;}static int pvr2_ctl_get_hsm(struct pvr2_ctrl *cptr){ int result = pvr2_hdw_is_hsm(cptr->hdw); if (result < 0) return PVR2_CVAL_HSM_FAIL; if (result) return PVR2_CVAL_HSM_HIGH; return PVR2_CVAL_HSM_FULL;}int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw){ int result; LOCK_TAKE(hdw->ctl_lock); do { hdw->cmd_buffer[0] = 0x0b; result = pvr2_send_request(hdw, hdw->cmd_buffer,1, hdw->cmd_buffer,1); if (result < 0) break; result = (hdw->cmd_buffer[0] != 0); } while(0); LOCK_GIVE(hdw->ctl_lock); return result;}static int pvr2_ctl_get_signal(struct pvr2_ctrl *cptr){ return ((pvr2_hdw_get_signal_status_internal(cptr->hdw) & PVR2_SIGNAL_OK) ? 1 : 0);}/* Return bit mask indicating signal status */unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *hdw){ unsigned int msk = 0; LOCK_TAKE(hdw->big_lock); do { msk = pvr2_hdw_get_signal_status_internal(hdw); } while (0); LOCK_GIVE(hdw->big_lock); return msk;}/* Get handle
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -