static int smsdvb_update_stats(struct smsdvb_client_t *client, struct dvb_frontend *fe) { int rc=0; unsigned long time_now = jiffies_to_msecs(jiffies); /* * warning : do not remove this operation mode check * smsdvb_get_statistics_ex will fail on DVBT */ if (smscore_get_device_mode(client->coredev) == DEVICE_MODE_DVBT_BDA) { return rc; } if ( (!client->last_sample_time) || (time_now - client->last_sample_time > 100) ) { /*sms_debug("%lu ms since last sample time, getting statistics", (time_now - client->last_sample_time));*/ rc = smsdvb_get_statistics_ex(fe); if (rc < 0) { sms_err("error in smsdvb_get_statistics_ex, rc = %d", rc); return rc; } } return rc; }
static void smsdvb_stats_not_ready(struct dvb_frontend *fe) { struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); struct smscore_device_t *coredev = client->coredev; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int i, n_layers; switch (smscore_get_device_mode(coredev)) { case DEVICE_MODE_ISDBT: case DEVICE_MODE_ISDBT_BDA: n_layers = 4; break; default: n_layers = 1; } /* Global stats */ c->strength.len = 1; c->cnr.len = 1; c->strength.stat[0].scale = FE_SCALE_DECIBEL; c->cnr.stat[0].scale = FE_SCALE_DECIBEL; /* Per-layer stats */ c->post_bit_error.len = n_layers; c->post_bit_count.len = n_layers; c->block_error.len = n_layers; c->block_count.len = n_layers; /* * Put all of them at FE_SCALE_NOT_AVAILABLE. They're dynamically * changed when the stats become available. */ for (i = 0; i < n_layers; i++) { c->post_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; c->post_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; c->block_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; c->block_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; } }
static int smsdvb_set_frontend(struct dvb_frontend *fe) { struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); struct smscore_device_t *coredev = client->coredev; smsdvb_stats_not_ready(fe); c->strength.stat[0].uvalue = 0; c->cnr.stat[0].uvalue = 0; client->has_tuned = false; switch (smscore_get_device_mode(coredev)) { case DEVICE_MODE_DVBT: case DEVICE_MODE_DVBT_BDA: return smsdvb_dvbt_set_frontend(fe); case DEVICE_MODE_ISDBT: case DEVICE_MODE_ISDBT_BDA: return smsdvb_isdbt_set_frontend(fe); default: return -EINVAL; } }
static int smsdvb_send_statistics_request(struct smsdvb_client_t *client) { int rc; struct sms_msg_hdr msg; /* Don't request stats too fast */ if (client->get_stats_jiffies && (!time_after(jiffies, client->get_stats_jiffies))) return 0; client->get_stats_jiffies = jiffies + msecs_to_jiffies(100); msg.msg_src_id = DVBT_BDA_CONTROL_MSG_ID; msg.msg_dst_id = HIF_TASK; msg.msg_flags = 0; msg.msg_length = sizeof(msg); switch (smscore_get_device_mode(client->coredev)) { case DEVICE_MODE_ISDBT: case DEVICE_MODE_ISDBT_BDA: /* * Check for firmware version, to avoid breaking for old cards */ if (client->coredev->fw_version >= 0x800) msg.msg_type = MSG_SMS_GET_STATISTICS_EX_REQ; else msg.msg_type = MSG_SMS_GET_STATISTICS_REQ; break; default: msg.msg_type = MSG_SMS_GET_STATISTICS_REQ; } rc = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg), &client->stats_done); return rc; }
static int smsdvb_hotplug(struct smscore_device_t *coredev, struct device *device, int arrival) { struct smsclient_params_t params; struct smsdvb_client_t *client; int rc; /* device removal handled by onremove callback */ if (!arrival) return 0; if (smscore_get_device_mode(coredev) != 4) { sms_err("SMS Device mode is not set for " "DVB operation."); return 0; } client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL); if (!client) { sms_err("kmalloc() failed"); return -ENOMEM; } /* register dvb adapter */ rc = dvb_register_adapter(&client->adapter, sms_get_board( smscore_get_board_id(coredev))->name, THIS_MODULE, device, adapter_nr); if (rc < 0) { sms_err("dvb_register_adapter() failed %d", rc); goto adapter_error; } /* init dvb demux */ client->demux.dmx.capabilities = DMX_TS_FILTERING; client->demux.filternum = 32; /* todo: nova ??? */ client->demux.feednum = 32; client->demux.start_feed = smsdvb_start_feed; client->demux.stop_feed = smsdvb_stop_feed; rc = dvb_dmx_init(&client->demux); if (rc < 0) { sms_err("dvb_dmx_init failed %d", rc); goto dvbdmx_error; } /* init dmxdev */ client->dmxdev.filternum = 32; client->dmxdev.demux = &client->demux.dmx; client->dmxdev.capabilities = 0; rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter); if (rc < 0) { sms_err("dvb_dmxdev_init failed %d", rc); goto dmxdev_error; } /* init and register frontend */ memcpy(&client->frontend.ops, &smsdvb_fe_ops, sizeof(struct dvb_frontend_ops)); rc = dvb_register_frontend(&client->adapter, &client->frontend); if (rc < 0) { sms_err("frontend registration failed %d", rc); goto frontend_error; } params.initial_id = 1; params.data_type = MSG_SMS_DVBT_BDA_DATA; params.onresponse_handler = smsdvb_onresponse; params.onremove_handler = smsdvb_onremove; params.context = client; rc = smscore_register_client(coredev, ¶ms, &client->smsclient); if (rc < 0) { sms_err("smscore_register_client() failed %d", rc); goto client_error; } client->coredev = coredev; init_completion(&client->tune_done); init_completion(&client->stat_done); kmutex_lock(&g_smsdvb_clientslock); list_add(&client->entry, &g_smsdvb_clients); kmutex_unlock(&g_smsdvb_clientslock); sms_info("success"); sms_board_setup(coredev); return 0; client_error: dvb_unregister_frontend(&client->frontend); frontend_error: dvb_dmxdev_release(&client->dmxdev); dmxdev_error: dvb_dmx_release(&client->demux); dvbdmx_error: dvb_unregister_adapter(&client->adapter); adapter_error: kfree(client); return rc; }
static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) { struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) (((u8 *) cb->p) + cb->offset); void *p = phdr + 1; struct dvb_frontend *fe = &client->frontend; struct dtv_frontend_properties *c = &fe->dtv_property_cache; bool is_status_update = false; switch (phdr->msg_type) { case MSG_SMS_DVBT_BDA_DATA: /* * Only feed data to dvb demux if are there any feed listening * to it and if the device has tuned */ if (client->feed_users && client->has_tuned) dvb_dmx_swfilter(&client->demux, p, cb->size - sizeof(struct sms_msg_hdr)); break; case MSG_SMS_RF_TUNE_RES: case MSG_SMS_ISDBT_TUNE_RES: complete(&client->tune_done); break; case MSG_SMS_SIGNAL_DETECTED_IND: client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; is_status_update = true; break; case MSG_SMS_NO_SIGNAL_IND: client->fe_status = 0; is_status_update = true; break; case MSG_SMS_TRANSMISSION_IND: smsdvb_update_tx_params(client, p); is_status_update = true; break; case MSG_SMS_HO_PER_SLICES_IND: smsdvb_update_per_slices(client, p); is_status_update = true; break; case MSG_SMS_GET_STATISTICS_RES: switch (smscore_get_device_mode(client->coredev)) { case DEVICE_MODE_ISDBT: case DEVICE_MODE_ISDBT_BDA: smsdvb_update_isdbt_stats(client, p); break; default: /* Skip sms_msg_statistics_info:request_result field */ smsdvb_update_dvb_stats(client, p + sizeof(u32)); } is_status_update = true; break; /* Only for ISDB-T */ case MSG_SMS_GET_STATISTICS_EX_RES: /* Skip sms_msg_statistics_info:request_result field? */ smsdvb_update_isdbt_stats_ex(client, p + sizeof(u32)); is_status_update = true; break; default: pr_debug("message not handled\n"); } smscore_putbuffer(client->coredev, cb); if (is_status_update) { if (client->fe_status & FE_HAS_LOCK) { sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK); if (client->last_per == c->block_error.stat[0].uvalue) sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK); else sms_board_dvb3_event(client, DVB3_EVENT_UNC_ERR); client->has_tuned = true; } else { smsdvb_stats_not_ready(fe); client->has_tuned = false; sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK); } complete(&client->stats_done); } return 0; }
static int smsdvb_hotplug(struct smscore_device_t *coredev, struct device *device, int arrival) { struct smsclient_params_t params; struct smsdvb_client_t *client; int rc; /* device removal handled by onremove callback */ if (!arrival) return 0; client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL); if (!client) return -ENOMEM; /* register dvb adapter */ rc = dvb_register_adapter(&client->adapter, sms_get_board( smscore_get_board_id(coredev))->name, THIS_MODULE, device, adapter_nr); if (rc < 0) { pr_err("dvb_register_adapter() failed %d\n", rc); goto adapter_error; } dvb_register_media_controller(&client->adapter, coredev->media_dev); /* init dvb demux */ client->demux.dmx.capabilities = DMX_TS_FILTERING; client->demux.filternum = 32; /* todo: nova ??? */ client->demux.feednum = 32; client->demux.start_feed = smsdvb_start_feed; client->demux.stop_feed = smsdvb_stop_feed; rc = dvb_dmx_init(&client->demux); if (rc < 0) { pr_err("dvb_dmx_init failed %d\n", rc); goto dvbdmx_error; } /* init dmxdev */ client->dmxdev.filternum = 32; client->dmxdev.demux = &client->demux.dmx; client->dmxdev.capabilities = 0; rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter); if (rc < 0) { pr_err("dvb_dmxdev_init failed %d\n", rc); goto dmxdev_error; } /* init and register frontend */ memcpy(&client->frontend.ops, &smsdvb_fe_ops, sizeof(struct dvb_frontend_ops)); switch (smscore_get_device_mode(coredev)) { case DEVICE_MODE_DVBT: case DEVICE_MODE_DVBT_BDA: client->frontend.ops.delsys[0] = SYS_DVBT; break; case DEVICE_MODE_ISDBT: case DEVICE_MODE_ISDBT_BDA: client->frontend.ops.delsys[0] = SYS_ISDBT; break; } rc = dvb_register_frontend(&client->adapter, &client->frontend); if (rc < 0) { pr_err("frontend registration failed %d\n", rc); goto frontend_error; } params.initial_id = 1; params.data_type = MSG_SMS_DVBT_BDA_DATA; params.onresponse_handler = smsdvb_onresponse; params.onremove_handler = smsdvb_onremove; params.context = client; rc = smscore_register_client(coredev, ¶ms, &client->smsclient); if (rc < 0) { pr_err("smscore_register_client() failed %d\n", rc); goto client_error; } client->coredev = coredev; init_completion(&client->tune_done); init_completion(&client->stats_done); kmutex_lock(&g_smsdvb_clientslock); list_add(&client->entry, &g_smsdvb_clients); kmutex_unlock(&g_smsdvb_clientslock); client->event_fe_state = -1; client->event_unc_state = -1; sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG); sms_board_setup(coredev); if (smsdvb_debugfs_create(client) < 0) pr_info("failed to create debugfs node\n"); rc = dvb_create_media_graph(&client->adapter, true); if (rc < 0) { pr_err("dvb_create_media_graph failed %d\n", rc); goto client_error; } pr_info("DVB interface registered.\n"); return 0; client_error: dvb_unregister_frontend(&client->frontend); frontend_error: dvb_dmxdev_release(&client->dmxdev); dmxdev_error: dvb_dmx_release(&client->demux); dvbdmx_error: smsdvb_media_device_unregister(client); dvb_unregister_adapter(&client->adapter); adapter_error: kfree(client); return rc; }
static int smschar_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct smschar_device_t *dev = file->private_data; void __user *up = (void __user *)arg; if (!dev->coredev || !dev->smsclient) { sms_err("no client\n"); return -ENODEV; } switch (cmd) { case SMSCHAR_SET_DEVICE_MODE: return smscore_set_device_mode(dev->coredev, (int)arg); case SMSCHAR_GET_DEVICE_MODE: { if (put_user(smscore_get_device_mode(dev->coredev), (int *)up)) return -EFAULT; break; } case SMSCHAR_IS_DEVICE_PNP_EVENT: { sms_info("Waiting for PnP event.\n"); wait_event_interruptible(g_pnp_event, !g_pnp_status_changed); g_pnp_status_changed = 0; sms_info("PnP Event %d.\n", g_smschar_inuse); if (put_user(g_smschar_inuse, (int *)up)) return -EFAULT; break; } case SMSCHAR_GET_BUFFER_SIZE: { if (put_user (smscore_get_common_buffer_size(dev->coredev), (int *)up)) return -EFAULT; break; } case SMSCHAR_WAIT_GET_BUFFER: { struct smschar_buffer_t touser; int rc; rc = smschar_wait_get_buffer(dev, &touser); if (rc < 0) return rc; if (copy_to_user(up, &touser, sizeof(struct smschar_buffer_t))) return -EFAULT; break; } case SMSCHAR_CANCEL_WAIT_BUFFER: { dev->cancel_waitq = 1; wake_up_interruptible(&dev->waitq); break; } case SMSCHAR_CANCEL_POLL: { /*obsollete*/ break; } case SMSCHAR_GET_FW_FILE_NAME: { if (!up) return -EINVAL; return smschar_get_fw_filename(dev, (struct smschar_get_fw_filename_ioctl_t*)up); } case SMSCHAR_SEND_FW_FILE: { if (!up) return -EINVAL; return smschar_send_fw_file(dev, (struct smschar_send_fw_file_ioctl_t*)up); } default: return -ENOIOCTLCMD; } return 0; }
static int smsdvb_hotplug(struct smscore_device_t *coredev, struct device *device, int arrival) { struct smsclient_params_t params; struct smsdvb_client_t *client; int rc; int mode = smscore_get_device_mode(coredev); //mode = 6; /* device removal handled by onremove callback */ if (!arrival) return 0; if ( (mode != DEVICE_MODE_DVBT_BDA) && (mode != DEVICE_MODE_ISDBT_BDA) ) { sms_err("SMS Device mode is not set for " "DVB operation."); return 0; } client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL); if (!client) { sms_err("kmalloc() failed"); return -ENOMEM; } /* register dvb adapter */ #ifdef SMS_DVB_OLD_DVB_REGISTER_ADAPTER rc = dvb_register_adapter(&client->adapter, sms_get_board(smscore_get_board_id(coredev))-> name, THIS_MODULE, device); #else rc = dvb_register_adapter(&client->adapter, sms_get_board(smscore_get_board_id(coredev))-> name, THIS_MODULE, device, adapter_nr); #endif if (rc < 0) { sms_err("dvb_register_adapter() failed %d", rc); goto adapter_error; } /* init dvb demux */ client->demux.dmx.capabilities = DMX_TS_FILTERING; client->demux.filternum = 32; /* todo: nova ??? */ client->demux.feednum = 32; client->demux.start_feed = smsdvb_start_feed; client->demux.stop_feed = smsdvb_stop_feed; rc = dvb_dmx_init(&client->demux); if (rc < 0) { sms_err("dvb_dmx_init failed %d", rc); goto dvbdmx_error; } /* init dmxdev */ client->dmxdev.filternum = 32; client->dmxdev.demux = &client->demux.dmx; client->dmxdev.capabilities = 0; rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter); if (rc < 0) { sms_err("dvb_dmxdev_init failed %d", rc); goto dmxdev_error; } //add by luis printk("debug: %s, %d, %s>>>>>>>>>>>>>>>>>>>>\n", __FILE__, __LINE__, __FUNCTION__); //add by luis /* init and register frontend */ memcpy(&client->frontend.ops, &smsdvb_fe_ops, sizeof(struct dvb_frontend_ops)); //add by luis printk("debug: %s, %d, %s>>>>>>>>>>>>>>>>>>>>\n", __FILE__, __LINE__, __FUNCTION__); //add by luis rc = dvb_register_frontend(&client->adapter, &client->frontend); if (rc < 0) { sms_err("frontend registration failed %d", rc); goto frontend_error; } params.initial_id = 1; params.data_type = MSG_SMS_DVBT_BDA_DATA; params.onresponse_handler = smsdvb_onresponse; params.onremove_handler = smsdvb_onremove; params.context = client; //add by luis printk("debug: %s, %d, %s>>>>>>>>>>>>>>>>>>>>\n", __FILE__, __LINE__, __FUNCTION__); //add by luis rc = smscore_register_client(coredev, ¶ms, &client->smsclient); if (rc < 0) { sms_err("smscore_register_client() failed %d", rc); goto client_error; } client->coredev = coredev; init_completion(&client->tune_done); init_completion(&client->get_stats_done); kmutex_lock(&g_smsdvb_clientslock); list_add(&client->entry, &g_smsdvb_clients); kmutex_unlock(&g_smsdvb_clientslock); client->event_fe_state = -1; client->event_unc_state = -1; sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG); //add by luis printk("debug: %s, %d, %s>>>>>>>>>>>>>>>>>>>>\n", __FILE__, __LINE__, __FUNCTION__); //add by luis sms_info("success"); return 0; client_error: dvb_unregister_frontend(&client->frontend); frontend_error: dvb_dmxdev_release(&client->dmxdev); dmxdev_error: dvb_dmx_release(&client->demux); dvbdmx_error: dvb_unregister_adapter(&client->adapter); adapter_error: kfree(client); return rc; }