📄 pvrusb2-hdw.c
字号:
pvr2_trace(PVR2_TRACE_CTL, "/*---TRACE_CTL----*/" " pvr2_hdw_cmd_usbstream(1)"); pvr2_hdw_cmd_usbstream(hdw,!0); } if (vmsk & PVR2_SUBSYS_ENC_RUN) { pvr2_trace(PVR2_TRACE_CTL, "/*---TRACE_CTL----*/" " pvr2_encoder_start"); ret = pvr2_encoder_start(hdw); if (ret) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Error recovery initiated"); hdw->subsys_enabled_mask &= ~FIRMWARE_RECOVERY_BITS; continue; } } } }}void pvr2_hdw_subsys_bit_chg(struct pvr2_hdw *hdw, unsigned long msk,unsigned long val){ LOCK_TAKE(hdw->big_lock); do { pvr2_hdw_subsys_bit_chg_no_lock(hdw,msk,val); } while (0); LOCK_GIVE(hdw->big_lock);}void pvr2_hdw_subsys_bit_set(struct pvr2_hdw *hdw,unsigned long msk){ pvr2_hdw_subsys_bit_chg(hdw,msk,msk);}void pvr2_hdw_subsys_bit_clr(struct pvr2_hdw *hdw,unsigned long msk){ pvr2_hdw_subsys_bit_chg(hdw,msk,0);}unsigned long pvr2_hdw_subsys_get(struct pvr2_hdw *hdw){ return hdw->subsys_enabled_mask;}unsigned long pvr2_hdw_subsys_stream_get(struct pvr2_hdw *hdw){ return hdw->subsys_stream_mask;}void pvr2_hdw_subsys_stream_bit_chg_no_lock(struct pvr2_hdw *hdw, unsigned long msk, unsigned long val){ unsigned long val2; msk &= PVR2_SUBSYS_ALL; val2 = ((hdw->subsys_stream_mask & ~msk) | (val & msk)); pvr2_trace(PVR2_TRACE_INIT, "stream mask changing 0x%lx:0x%lx from 0x%lx to 0x%lx", msk,val,hdw->subsys_stream_mask,val2); hdw->subsys_stream_mask = val2;}void pvr2_hdw_subsys_stream_bit_chg(struct pvr2_hdw *hdw, unsigned long msk, unsigned long val){ LOCK_TAKE(hdw->big_lock); do { pvr2_hdw_subsys_stream_bit_chg_no_lock(hdw,msk,val); } while (0); LOCK_GIVE(hdw->big_lock);}static int pvr2_ctl_get_streaming(struct pvr2_ctrl *cptr){ return cptr->hdw->flag_streaming_enabled != 0;}int pvr2_hdw_set_streaming_no_lock(struct pvr2_hdw *hdw,int enableFl){ if ((!enableFl) == !(hdw->flag_streaming_enabled)) return 0; if (enableFl) { pvr2_trace(PVR2_TRACE_START_STOP, "/*--TRACE_STREAM--*/ enable"); pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,~0); } else { pvr2_trace(PVR2_TRACE_START_STOP, "/*--TRACE_STREAM--*/ disable"); pvr2_hdw_subsys_bit_chg_no_lock(hdw,hdw->subsys_stream_mask,0); } if (!hdw->flag_ok) return -EIO; hdw->flag_streaming_enabled = enableFl != 0; return 0;}int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw){ return hdw->flag_streaming_enabled != 0;}int pvr2_hdw_set_streaming(struct pvr2_hdw *hdw,int enable_flag){ int ret; LOCK_TAKE(hdw->big_lock); do { ret = pvr2_hdw_set_streaming_no_lock(hdw,enable_flag); } while (0); LOCK_GIVE(hdw->big_lock); return ret;}int pvr2_hdw_set_stream_type_no_lock(struct pvr2_hdw *hdw, enum pvr2_config config){ unsigned long sm = hdw->subsys_enabled_mask; if (!hdw->flag_ok) return -EIO; pvr2_hdw_subsys_bit_chg_no_lock(hdw,hdw->subsys_stream_mask,0); hdw->config = config; pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,sm); return 0;}int pvr2_hdw_set_stream_type(struct pvr2_hdw *hdw,enum pvr2_config config){ int ret; if (!hdw->flag_ok) return -EIO; LOCK_TAKE(hdw->big_lock); ret = pvr2_hdw_set_stream_type_no_lock(hdw,config); LOCK_GIVE(hdw->big_lock); return ret;}static int get_default_tuner_type(struct pvr2_hdw *hdw){ int unit_number = hdw->unit_number; int tp = -1; if ((unit_number >= 0) && (unit_number < PVR_NUM)) { tp = tuner[unit_number]; } if (tp < 0) return -EINVAL; hdw->tuner_type = tp; return 0;}static unsigned int get_default_error_tolerance(struct pvr2_hdw *hdw){ int unit_number = hdw->unit_number; int tp = 0; if ((unit_number >= 0) && (unit_number < PVR_NUM)) { tp = tolerance[unit_number]; } return tp;}static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw){ /* Try a harmless request to fetch the eeprom's address over endpoint 1. See what happens. Only the full FX2 image can respond to this. If this probe fails then likely the FX2 firmware needs be loaded. */ int result; LOCK_TAKE(hdw->ctl_lock); do { hdw->cmd_buffer[0] = 0xeb; result = pvr2_send_request_ex(hdw,HZ*1,!0, hdw->cmd_buffer,1, hdw->cmd_buffer,1); if (result < 0) break; } while(0); LOCK_GIVE(hdw->ctl_lock); if (result) { pvr2_trace(PVR2_TRACE_INIT, "Probe of device endpoint 1 result status %d", result); } else { pvr2_trace(PVR2_TRACE_INIT, "Probe of device endpoint 1 succeeded"); } return result == 0;}static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw){ int ret; unsigned int idx; struct pvr2_ctrl *cptr; int reloadFl = 0; if (!reloadFl) { reloadFl = (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints == 0); if (reloadFl) { pvr2_trace(PVR2_TRACE_INIT, "USB endpoint config looks strange" "; possibly firmware needs to be loaded"); } } if (!reloadFl) { reloadFl = !pvr2_hdw_check_firmware(hdw); if (reloadFl) { pvr2_trace(PVR2_TRACE_INIT, "Check for FX2 firmware failed" "; possibly firmware needs to be loaded"); } } if (reloadFl) { if (pvr2_upload_firmware1(hdw) != 0) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Failure uploading firmware1"); } return; } hdw->fw1_state = FW1_STATE_OK; if (initusbreset) { pvr2_hdw_device_reset(hdw); } if (!pvr2_hdw_dev_ok(hdw)) return; pvr2_hdw_cmd_powerup(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; if (pvr2_upload_firmware2(hdw)){ pvr2_trace(PVR2_TRACE_ERROR_LEGS,"device unstable!!"); pvr2_hdw_render_useless(hdw); return; } // This step MUST happen after the earlier powerup step. pvr2_i2c_core_init(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; for (idx = 0; idx < CTRL_COUNT; idx++) { cptr = hdw->controls + idx; if (!pvr2_ctrl_is_valid(cptr)) continue; if (cptr->ctl_def->skip_init) continue; pvr2_ctrl_internal_set_value(cptr, cptr->ctl_def->default_value); } // Do not use pvr2_reset_ctl_endpoints() here. It is not // thread-safe against the normal pvr2_send_request() mechanism. // (We should make it thread safe). ret = pvr2_hdw_get_eeprom_addr(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; if (ret < 0) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Unable to determine location of eeprom, skipping"); } else { hdw->eeprom_addr = ret; pvr2_eeprom_analyze(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; } if (!get_default_tuner_type(hdw)) { pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_setup: Tuner type overridden to %d", hdw->tuner_type); } hdw->tuner_updated = !0; pvr2_i2c_core_check_stale(hdw); hdw->tuner_updated = 0; if (!pvr2_hdw_dev_ok(hdw)) return; for (idx = 0; idx < hdw->std_cnt; idx++) { pvr2_trace(PVR2_TRACE_EEPROM, "Detected video standard %s (from eeprom)", hdw->std_defs[idx].name); } if (hdw->std_cnt) { pvr2_trace(PVR2_TRACE_EEPROM, "Initial video standard set to %s" " (detected from eeprom)", hdw->std_defs[hdw->std_id].name); } else { pvr2_trace(PVR2_TRACE_EEPROM, "Unable to select a viable video standard"); } if (!pvr2_hdw_dev_ok(hdw)) return; pvr2_hdw_commit_ctl_internal(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; hdw->vid_stream = pvr2_stream_create(); if (!pvr2_hdw_dev_ok(hdw)) return; pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_setup: video stream is %p",hdw->vid_stream); if (hdw->vid_stream) { idx = get_default_error_tolerance(hdw); if (idx) { pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_setup: video stream %p" " setting tolerance %u", hdw->vid_stream,idx); } pvr2_stream_setup(hdw->vid_stream,hdw->usb_dev, PVR2_VID_ENDPOINT,idx); } if (!pvr2_hdw_dev_ok(hdw)) return; /* Make sure everything is up to date */ pvr2_i2c_core_sync(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; hdw->flag_init_ok = !0;}int pvr2_hdw_setup(struct pvr2_hdw *hdw){ pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) begin",hdw); LOCK_TAKE(hdw->big_lock); do { pvr2_hdw_setup_low(hdw); pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_setup(hdw=%p) done, ok=%d init_ok=%d", hdw,hdw->flag_ok,hdw->flag_init_ok); if (pvr2_hdw_dev_ok(hdw)) { if (pvr2_hdw_init_ok(hdw)) { pvr2_trace( PVR2_TRACE_INFO, "Device initialization" " completed successfully."); break; } if (hdw->fw1_state == FW1_STATE_RELOAD) { pvr2_trace( PVR2_TRACE_INFO, "Device microcontroller firmware" " (re)loaded; it should now reset" " and reconnect."); break; } pvr2_trace( PVR2_TRACE_ERROR_LEGS, "Device initialization was not successful."); if (hdw->fw1_state == FW1_STATE_MISSING) { pvr2_trace( PVR2_TRACE_ERROR_LEGS, "Giving up since device" " microcontroller firmware" " appears to be missing."); break; } } if (procreload) { pvr2_trace( PVR2_TRACE_ERROR_LEGS, "Attempting pvrusb2 recovery by reloading" " primary firmware."); pvr2_trace( PVR2_TRACE_ERROR_LEGS, "If this works, device should disconnect" " and reconnect in a sane state."); hdw->fw1_state = FW1_STATE_UNKNOWN; pvr2_upload_firmware1(hdw); } else { pvr2_trace( PVR2_TRACE_ERROR_LEGS, "***WARNING*** pvrusb2 device hardware" " appears to be jammed" " and I can't clear it."); pvr2_trace( PVR2_TRACE_ERROR_LEGS, "You might need to power cycle" " the pvrusb2 device" " in order to recover."); } } while (0); LOCK_GIVE(hdw->big_lock); pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) end",hdw); return hdw->flag_init_ok;}/* Create and return a structure for interacting with the underlying hardware */struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, const struct usb_device_id *devid){ unsigned int idx,cnt1,cnt2; struct pvr2_hdw *hdw; unsigned int hdw_type; __u8 ifnum; hdw_type = devid - pvr2_device_table; if (hdw_type >= sizeof(pvr2_device_names)/sizeof(pvr2_device_names[0])) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Bogus device type of %u reported",hdw_type); return 0; } hdw = kmalloc(sizeof(*hdw),GFP_KERNEL); pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", hdw,pvr2_device_names[hdw_type]); if (!hdw) goto fail; memset(hdw,0,sizeof(*hdw)); // Initialize video standard enum dynamic control hdw->video_std_enum.name = "video_standard"; hdw->video_std_enum.desc = "Video Standard Name"; hdw->video_std_enum.id = 0; // ????? hdw->video_std_enum.set_func = pvr2_ctl_set_stdenumcur; hdw->video_std_enum.get_func = pvr2_ctl_get_stdenumcur; hdw->video_std_enum.mask_value = 0; hdw->video_std_enum.max_value = 0; hdw->video_std_enum.min_value = 0; hdw->video_std_enum.default_value = 0; hdw->video_std_enum.is_valid = !0; hdw->controls = kmalloc(sizeof(struct pvr2_ctrl) * CTRL_COUNT, GFP_KERNEL); if (!hdw->controls) goto fail; memset(hdw->controls,0,sizeof(struct pvr2_ctrl) * CTRL_COUNT); hdw->hdw_type = hdw_type; for (idx = 0; idx < CTRL_DEF_COUNT; idx++) { hdw->controls[idx].hdw = hdw; hdw->controls[idx].ctl_def = control_defs + idx; hdw->controls[idx].is_valid = hdw->controls[idx].ctl_def->is_valid; } hdw->controls[PVR2_CID_STDNAME].hdw = hdw; hdw->controls[PVR2_CID_STDNAME].ctl_def = &hdw->video_std_enum; hdw->controls[PVR2_CID_STDNAME].is_valid = !0; hdw->eeprom_addr = -1; hdw->unit_number = -1; hdw->v4l_minor_number = -1; hdw->ctl_write_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL); if (!hdw->ctl_write_buffer) goto fail; hdw->ctl_read_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL); if (!hdw->ctl_read_buffer) goto fail; hdw->ctl_write_urb = usb_alloc_urb(0,GFP_KERNEL); if (!hdw->ctl_write_urb) goto fail; hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL); if (!hdw->ctl_read_urb) goto fail; down(&pvr2_unit_sem); do { for (idx = 0; idx < PVR_NUM; idx++) { if (unit_pointers[idx]) continue; hdw->unit_number = idx; unit_pointers[idx] = hdw; break; } } while (0); up(&pvr2_unit_sem); cnt1 = 0; cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2"); cnt1 += cnt2; if (hdw->unit_number >= 0) { cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"_%c", ('a' + hdw->unit_number)); cnt1 += cnt2; } if (cnt1 >= sizeof(hdw->name)) cnt1 = sizeof(hdw->name)-1; hdw->name[cnt1] = 0; pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s", hdw->unit_number,hdw->name); hdw->tuner_type = -1; hdw->flag_ok = !0; /* Initialize the mask of subsystems that we will shut down when we stop streaming. */ hdw->subsys_stream_mask = PVR2_SUBSYS_RUN_ALL; hdw->subsys_stream_mask |= PVR2_SUBSYS_ENC_CFG; pvr2_trace(PVR2_TRACE_INIT,"subsys_stream_mask: 0x%lx", hdw->subsys_stream_mask); hdw->usb_intf = intf; hdw->usb_dev = interface_to_usbdev(intf); ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber; usb_set_interface(hdw->usb_dev,ifnum,0); mutex_init(&hdw->ctl_lock_mutex);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -