/** * unregisters sms client and returns all queued buffers * * @param dev pointer to the client context (smschar parameters block) * */ static void smschar_unregister_client(struct smschar_device_t *dev) { unsigned long flags; if (dev->coredev && dev->smsclient) { dev->cancel_waitq = 1; wake_up_interruptible(&dev->waitq); spin_lock_irqsave(&dev->lock, flags); while (!list_empty(&dev->pending_data)) { struct smscore_buffer_t *cb = (struct smscore_buffer_t *)dev->pending_data.next; list_del(&cb->entry); smscore_putbuffer(dev->coredev, cb); dev->pending_count--; } if (dev->currentcb) { smscore_putbuffer(dev->coredev, dev->currentcb); dev->currentcb = NULL; dev->pending_count--; } smscore_unregister_client(dev->smsclient); dev->smsclient = NULL; spin_unlock_irqrestore(&dev->lock, flags); } }
static void free_rx_buf(void *context, struct _rx_buffer_st *buf) { struct _spi_device_st *spi_device = (struct _spi_device_st *) context; struct smscore_buffer_t *cb = (struct smscore_buffer_t *)(container_of(((void *)buf), struct smscore_buffer_t, p)); // printk("smsmdtv: buffer %p is released.\n", cb); smscore_putbuffer(spi_device->coredev, cb); }
static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) { struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)(((u8 *) cb->p) + cb->offset); switch (phdr->msgType) { case MSG_SMS_DVBT_BDA_DATA: dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1), cb->size - sizeof(struct SmsMsgHdr_ST)); break; case MSG_SMS_RF_TUNE_RES: complete(&client->tune_done); break; case MSG_SMS_GET_STATISTICS_RES: { struct SmsMsgStatisticsInfo_ST *p = (struct SmsMsgStatisticsInfo_ST *)(phdr + 1); if (p->Stat.IsDemodLocked) { client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; client->fe_snr = p->Stat.SNR; client->fe_ber = p->Stat.BER; client->fe_unc = p->Stat.BERErrorCount; if (p->Stat.InBandPwr < -95) client->fe_signal_strength = 0; else if (p->Stat.InBandPwr > -29) client->fe_signal_strength = 100; else client->fe_signal_strength = (p->Stat.InBandPwr + 95) * 3 / 2; } else { client->fe_status = 0; client->fe_snr = client->fe_ber = client->fe_unc = client->fe_signal_strength = 0; } complete(&client->stat_done); break; } } smscore_putbuffer(client->coredev, cb); return 0; }
/** * waits until buffer inserted into a queue. when inserted buffer offset * are reportedto the calling process. previously reported buffer is * returned to smscore pool. * * @param dev pointer to smschar parameters block * @param touser pointer to a structure that receives incoming buffer offsets * * @return 0 on success, <0 on error. */ static int smschar_wait_get_buffer(struct smschar_device_t *dev, struct smschar_buffer_t *touser) { unsigned long flags; int rc; spin_lock_irqsave(&dev->lock, flags); if (dev->currentcb) { smscore_putbuffer(dev->coredev, dev->currentcb); dev->currentcb = NULL; dev->pending_count--; } spin_unlock_irqrestore(&dev->lock, flags); rc = wait_event_interruptible(dev->waitq, !list_empty(&dev->pending_data) || (dev->cancel_waitq)); if (rc < 0) { sms_err("wait_event_interruptible error, rc = %d", rc); return rc; } if (dev->cancel_waitq) { touser->offset = 0; touser->size = 0; return 0; } if (!dev->smsclient) { sms_err("no client\n"); return -ENODEV; } spin_lock_irqsave(&dev->lock, flags); if (!list_empty(&dev->pending_data)) { struct smscore_buffer_t *cb = (struct smscore_buffer_t *)dev->pending_data.next; touser->offset = cb->offset_in_common + cb->offset; touser->size = cb->size; list_del(&cb->entry); dev->currentcb = cb; } else { touser->offset = 0; touser->size = 0; } spin_unlock_irqrestore(&dev->lock, flags); return 0; }
/** * copies data from buffers in incoming queue into a user buffer * * @param file File structure. * @param buf Source buffer. * @param count Size of source buffer. * @param f_pos Position in file (ignored). * * @return Number of bytes read, or <0 on error. */ static ssize_t smschar_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos) { struct smschar_device_t *dev = file->private_data; unsigned long flags; int rc, copied = 0; if (!buf) { sms_err("bad pointer recieved from user"); return -EFAULT; } if (!dev->coredev || !dev->smsclient) { sms_err("no client\n"); return -ENODEV; } rc = wait_event_interruptible(dev->waitq, !list_empty(&dev->pending_data) || (dev->cancel_waitq)); if (rc < 0) { sms_err("wait_event_interruptible error %d\n", rc); return rc; } if (dev->cancel_waitq) return 0; if (!dev->smsclient) { sms_err("no client\n"); return -ENODEV; } spin_lock_irqsave(&dev->lock, flags); while (!list_empty(&dev->pending_data) && (copied < count)) { struct smscore_buffer_t *cb = (struct smscore_buffer_t *)dev->pending_data.next; int actual_size = min(((int)count - copied), cb->size); if (copy_to_user(&buf[copied], &((char *)cb->p)[cb->offset], actual_size)) { sms_err("copy_to_user failed\n"); spin_unlock_irqrestore(&dev->lock, flags); return -EFAULT; } copied += actual_size; cb->offset += actual_size; cb->size -= actual_size; if (!cb->size) { list_del(&cb->entry); smscore_putbuffer(dev->coredev, cb); dev->pending_count--; } } spin_unlock_irqrestore(&dev->lock, flags); return copied; }
static void smssdio_remove(struct sdio_func *func) { struct smssdio_device *smsdev; smsdev = sdio_get_drvdata(func); sdio_claim_host(func); if (smsdev->split_cb) smscore_putbuffer(smsdev->coredev, smsdev->split_cb); smscore_unregister_device(smsdev->coredev); sdio_release_irq(func); sdio_disable_func(func); sdio_release_host(func); kfree(smsdev); }
static void smsi2c_worker_thread(void *args) { struct smscore_buffer_t *cb; struct SmsMsgHdr_S *phdr; u16 len; int ret; u8 local_buf[100]; sms_debug("Worker thread is running.\n"); if (!g_smsi2c_device->coredev) { sms_debug("Using local buffer\n"); cb = NULL; phdr = (struct SmsMsgHdr_S *)local_buf; } else { sms_debug("Using core buffer\n"); cb = smscore_getbuffer(g_smsi2c_device->coredev); if (!cb) { sms_err("Unable to allocate data buffer!\n"); goto exit; } phdr = (struct SmsMsgHdr_S *)cb->p; } sms_debug("Recieve the message header.....\n"); memset(phdr, 0, (int)sizeof(struct SmsMsgHdr_S)); sms_debug("buf before: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", ((u8*)phdr)[0], ((u8*)phdr)[1], ((u8*)phdr)[2], ((u8*)phdr)[3], ((u8*)phdr)[4], ((u8*)phdr)[5], ((u8*)phdr)[6], ((u8*)phdr)[7]); #if 0 ret = i2c_master_recv(g_smsi2c_device->client, (void *)phdr, (int)sizeof(struct SmsMsgHdr_S)); #else ret = i2c_master_normal_recv(g_smsi2c_device->client, (void *)phdr, (int)sizeof(struct SmsMsgHdr_S), I2C_SCL_TATE); #endif if (ret < 0) { if ((void*)phdr != (void*)local_buf) smscore_putbuffer(g_smsi2c_device->coredev, cb); sms_err("Unable to read sms header! ret=%d\n", ret); goto exit; } #if 0 sms_debug("hdr: type=%d, src=%d, dst=%d, len=%d, flag=0x%x\n", phdr->msgType, phdr->msgSrcId, phdr->msgDstId, phdr->msgLength, phdr->msgFlags); sms_debug("buf: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", ((u8*)phdr)[0], ((u8*)phdr)[1], ((u8*)phdr)[2], ((u8*)phdr)[3], ((u8*)phdr)[4], ((u8*)phdr)[5], ((u8*)phdr)[6], ((u8*)phdr)[7]); sms_debug("Recieve the rest of the message.....\n"); #endif len = phdr->msgLength; if (len > sizeof(struct SmsMsgHdr_S)) { #if 0 ret = i2c_master_recv(g_smsi2c_device->client, (u8*)(phdr+1), len - (int)sizeof(struct SmsMsgHdr_S)); #else ret = i2c_master_normal_recv(g_smsi2c_device->client, (u8*)(phdr+1), len - (int)sizeof(struct SmsMsgHdr_S), I2C_SCL_TATE); #endif //sms_debug("recv of data returned %d", ret); if (ret < 0) { if ((void*)phdr != (void*)local_buf) smscore_putbuffer(g_smsi2c_device->coredev, cb); sms_err("Unable to read sms payload!\n"); goto exit; } sms_debug("data: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", ((u8*)(phdr+1))[0], ((u8*)(phdr+1))[1], ((u8*)(phdr+1))[2], ((u8*)(phdr+1))[3], ((u8*)(phdr+1))[4], ((u8*)(phdr+1))[5], ((u8*)(phdr+1))[6], ((u8*)(phdr+1))[7]); } if ((phdr->msgType == MSG_SMS_GET_VERSION_EX_RES) && ((void*)phdr == (void*)local_buf)) { /*This was an internal command, so we won't send it out*/ g_smsi2c_device->chip_model = *((u16*)(phdr+1)); sms_info("chip model=0x%x\n", g_smsi2c_device->chip_model); g_smsi2c_device->chip_metal = ((u8*)(phdr+1))[3]; sms_info("chip step=0x%x\n", g_smsi2c_device->chip_metal); g_smsi2c_device->wait_for_version_resp = 0; sms_info("complete get version\n"); complete(&g_smsi2c_device->version_ex_done); sms_info("done."); return; } #ifdef I2C_TS_ENABLE { if (MSG_SMS_INIT_DEVICE_RES == phdr->msgType) { ret = smsi2c_ts_enable(g_smsi2c_device); sms_debug("smsi2c_ts_enable.......\n"); } } #endif sms_debug("Message recieved. Sending to callback.....\n"); if (((void*)phdr != (void*)local_buf)) { sms_debug("Ext buf.....\n"); cb->offset = 0; cb->size = len; if (g_smsi2c_device->coredev) { smscore_onresponse(g_smsi2c_device->coredev, cb); } } exit: return; }
int smsnet_onresponse(void *context, struct smscore_buffer_t *cb) { struct smsnet_client_t *client = (struct smsnet_client_t *)context; int length, rest; u8 ip_ver, *buffer; buffer = ((u8 *) cb->p) + cb->offset + sizeof(struct SmsMsgHdr_ST); length = cb->size - sizeof(struct SmsMsgHdr_ST); if (client->splitheader_length) { /* how much data is missing ? */ rest = client->header_length - client->splitheader_length; /* do we have enough in this buffer ? */ rest = min(rest, length); memcpy(&client->splitpacket[client->splitheader_length], buffer, rest); client->splitheader_length += rest; if (client->splitheader_length != client->header_length) goto exit; if (check_header(client, client->splitpacket)) { buffer += rest; length -= rest; client->splitpacket_length = client->header_length; } client->splitheader_length = 0; } if (client->splitpacket_length) { /* how much data is missing ? */ rest = client->packet_length - client->splitpacket_length; /* do we have enough in this buffer ? */ rest = min(rest, length); memcpy(&client->splitpacket[client->splitpacket_length], buffer, rest); client->splitpacket_length += rest; if (client->splitpacket_length != client->packet_length) goto exit; client->splitpacket_length = 0; smsnet_send_packet(client->splitpacket, client->packet_length); buffer += rest; length -= rest; } while (length > 0) { ip_ver = GETIPVERSION(*buffer); while (length && (ip_ver != IPV4VERSION) && (ip_ver != IPV6VERSION)) { buffer++; length--; ip_ver = GETIPVERSION(*buffer); } /* No more data in section */ if (!length) break; /* Set the header length at start of packet according to the version no problem with the IP header cast, since we have at least 1 byte (we use only the first byte) */ client->header_length = (ip_ver == IPV4VERSION) ? (((struct iphdr *)buffer)->ihl * 4) : (sizeof(struct ipv6hdr) + sizeof(struct udphdr)); /*Check that Header length is at least 20 (min IPv4 length) */ if (client->header_length < 20) { length--; buffer++; continue; } /* check split header case */ if (client->header_length > length) { memcpy(client->splitpacket, buffer, length); client->splitheader_length = length; break; } if (check_header(client, buffer)) { /* check split packet case */ if (client->packet_length > length) { memcpy(client->splitpacket, buffer, length); client->splitpacket_length = length; break; } } else { length--; buffer++; continue; } smsnet_send_packet(buffer, client->packet_length); buffer += client->packet_length; length -= client->packet_length; } exit: smscore_putbuffer(client->coredev, cb); return 0; }
static void smssdio_interrupt(struct sdio_func *func) { int ret, isr; struct smssdio_device *smsdev; struct smscore_buffer_t *cb; struct SmsMsgHdr_ST *hdr; size_t size; smsdev = sdio_get_drvdata(func); /* * The interrupt register has no defined meaning. It is just * a way of turning of the level triggered interrupt. */ isr = sdio_readb(func, SMSSDIO_INT, &ret); if (ret) { dev_err(&smsdev->func->dev, "Unable to read interrupt register!\n"); return; } if (smsdev->split_cb == NULL) { cb = smscore_getbuffer(smsdev->coredev); if (!cb) { dev_err(&smsdev->func->dev, "Unable to allocate data buffer!\n"); return; } ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1); if (ret) { dev_err(&smsdev->func->dev, "Error %d reading initial block!\n", ret); return; } hdr = cb->p; if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) { smsdev->split_cb = cb; return; } size = hdr->msgLength - smsdev->func->cur_blksize; } else { cb = smsdev->split_cb; hdr = cb->p; size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST); smsdev->split_cb = NULL; } if (hdr->msgLength > smsdev->func->cur_blksize) { void *buffer; size = ALIGN(size, 128); buffer = cb->p + hdr->msgLength; BUG_ON(smsdev->func->cur_blksize != 128); /* * First attempt to transfer all of it in one go... */ ret = sdio_read_blocks(smsdev->func, buffer, SMSSDIO_DATA, size / 128); if (ret && ret != -EINVAL) { smscore_putbuffer(smsdev->coredev, cb); dev_err(&smsdev->func->dev, "Error %d reading data from card!\n", ret); return; } /* * ..then fall back to one block at a time if that is * not possible... * * (we have to do this manually because of the * problem with the "increase address" bit) */ if (ret == -EINVAL) { while (size) { ret = sdio_read_blocks(smsdev->func, buffer, SMSSDIO_DATA, 1); if (ret) { smscore_putbuffer(smsdev->coredev, cb); dev_err(&smsdev->func->dev, "Error %d reading " "data from card!\n", ret); return; } buffer += smsdev->func->cur_blksize; if (size > smsdev->func->cur_blksize) size -= smsdev->func->cur_blksize; else size = 0; } } } cb->size = hdr->msgLength; cb->offset = 0; smscore_onresponse(smsdev->coredev, cb); }
static void smssdio_work_thread(struct work_struct *arg) { int ret, isr; struct smscore_buffer_t *cb; struct SmsMsgHdr_S *hdr; size_t size; struct smssdio_device *smsdev = container_of(arg, struct smssdio_device, work_thread); struct sdio_func *sdfunc = smsdev->func; /* * The interrupt register has no defined meaning. It is just * a way of turning of the level triggered interrupt. */ sdio_claim_host(smsdev->func); isr = sdio_readb(smsdev->func, SMSSDIO_INT, &ret); if (ret) { sms_err("Got error reading interrupt status=%d, isr=%d\n", ret, isr); isr = sdio_readb(smsdev->func, SMSSDIO_INT, &ret); if (ret) { sms_err("Second read also failed, try to recover\n"); sdio_release_host(smsdev->func); sdfunc = kmemdup(smsdev->func, sizeof(struct sdio_func), GFP_KERNEL); if (!sdfunc) { sms_err("Out of memory!!!"); return; } sdfunc->num = 0; sdio_claim_host(sdfunc); sdio_writeb(sdfunc, 2, SMSSDIO_CCCR, &ret); sms_err("Read ISR status (write returned) %d\n", ret); isr = sdio_readb(smsdev->func, SMSSDIO_INT, &ret); sms_err("Read returned ret=%d, isr=%d\n", ret, isr); sdio_writeb(sdfunc, 0, SMSSDIO_CCCR, &ret); sdio_release_host(sdfunc); kfree(sdfunc); sms_err("Recovered, but this transaction is lost."); return; } sms_err("Second read succeed status=%d, isr=%d (continue)\n", ret, isr); } if (smsdev->split_cb == NULL) { cb = smscore_getbuffer(smsdev->coredev); if (!cb) { sms_err("Unable to allocate data buffer!\n"); sdio_release_host(smsdev->func); return; } ret = sdio_memcpy_fromio(smsdev->func, cb->p, SMSSDIO_DATA, SMSSDIO_BLOCK_SIZE); if (ret) { sms_warn("Error %d reading initial block, " "continue with sequence.\n", ret); } hdr = cb->p; if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) { smsdev->split_cb = cb; sdio_release_host(smsdev->func); return; } if (hdr->msgLength > smsdev->func->cur_blksize) size = hdr->msgLength - smsdev->func->cur_blksize; else size = 0; } else { cb = smsdev->split_cb; hdr = cb->p; size = hdr->msgLength - sizeof(struct SmsMsgHdr_S); smsdev->split_cb = NULL; } if (size) { void *buffer; buffer = cb->p + (hdr->msgLength - size); size = ALIGN(size, SMSSDIO_BLOCK_SIZE); BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE); /* * First attempt to transfer all of it in one go... */ ret = sdio_memcpy_fromio(smsdev->func, buffer, SMSSDIO_DATA, size); if (ret && ret != -EINVAL) { smscore_putbuffer(smsdev->coredev, cb); sms_err("Error %d reading data from card!\n", ret); sdio_release_host(smsdev->func); return; } /* * ..then fall back to one block at a time if that is * not possible... * * (we have to do this manually because of the * problem with the "increase address" bit) */ if (ret == -EINVAL) { while (size) { ret = sdio_memcpy_fromio(smsdev->func, buffer, SMSSDIO_DATA, smsdev->func->cur_blksize); if (ret) { smscore_putbuffer(smsdev->coredev, cb); sms_err("Error %d reading " "data from card!\n", ret); sdio_release_host(smsdev->func); return; } buffer += smsdev->func->cur_blksize; if (size > smsdev->func->cur_blksize) size -= smsdev->func->cur_blksize; else size = 0; } } } sdio_release_host(smsdev->func); cb->size = hdr->msgLength; cb->offset = 0; smscore_onresponse(smsdev->coredev, cb); }
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 void smssdio_interrupt(struct sdio_func *func) { int ret; struct smssdio_device *smsdev; struct smscore_buffer_t *cb; struct sms_msg_hdr *hdr; size_t size; smsdev = sdio_get_drvdata(func); /* * The interrupt register has no defined meaning. It is just * a way of turning of the level triggered interrupt. */ (void)sdio_readb(func, SMSSDIO_INT, &ret); if (ret) { pr_err("Unable to read interrupt register!\n"); return; } if (smsdev->split_cb == NULL) { cb = smscore_getbuffer(smsdev->coredev); if (!cb) { pr_err("Unable to allocate data buffer!\n"); return; } ret = sdio_memcpy_fromio(smsdev->func, cb->p, SMSSDIO_DATA, SMSSDIO_BLOCK_SIZE); if (ret) { pr_err("Error %d reading initial block!\n", ret); return; } hdr = cb->p; if (hdr->msg_flags & MSG_HDR_FLAG_SPLIT_MSG) { smsdev->split_cb = cb; return; } if (hdr->msg_length > smsdev->func->cur_blksize) size = hdr->msg_length - smsdev->func->cur_blksize; else size = 0; } else { cb = smsdev->split_cb; hdr = cb->p; size = hdr->msg_length - sizeof(struct sms_msg_hdr); smsdev->split_cb = NULL; } if (size) { void *buffer; buffer = cb->p + (hdr->msg_length - size); size = ALIGN(size, SMSSDIO_BLOCK_SIZE); BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE); /* * First attempt to transfer all of it in one go... */ ret = sdio_memcpy_fromio(smsdev->func, buffer, SMSSDIO_DATA, size); if (ret && ret != -EINVAL) { smscore_putbuffer(smsdev->coredev, cb); pr_err("Error %d reading data from card!\n", ret); return; } /* * ..then fall back to one block at a time if that is * not possible... * * (we have to do this manually because of the * problem with the "increase address" bit) */ if (ret == -EINVAL) { while (size) { ret = sdio_memcpy_fromio(smsdev->func, buffer, SMSSDIO_DATA, smsdev->func->cur_blksize); if (ret) { smscore_putbuffer(smsdev->coredev, cb); pr_err("Error %d reading data from card!\n", ret); return; } buffer += smsdev->func->cur_blksize; if (size > smsdev->func->cur_blksize) size -= smsdev->func->cur_blksize; else size = 0; } } } cb->size = hdr->msg_length; cb->offset = 0; smsendian_handle_rx_message((struct sms_msg_data *) cb->p); smscore_onresponse(smsdev->coredev, cb); }
static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) { struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p) + cb->offset); u32 *pMsgData = (u32 *) (phdr + 1); /*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/ bool is_status_update = false; smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr); switch (phdr->msgType) { case MSG_SMS_DVBT_BDA_DATA: dvb_dmx_swfilter(&client->demux, (u8 *) (phdr + 1), cb->size - sizeof(struct SmsMsgHdr_ST)); break; case MSG_SMS_ISDBT_TUNE_RES: sms_info("MSG_SMS_ISDBT_TUNE_RES"); case MSG_SMS_RF_TUNE_RES: complete(&client->tune_done); break; case MSG_SMS_SIGNAL_DETECTED_IND: sms_info("MSG_SMS_SIGNAL_DETECTED_IND"); client->sms_stat_dvb.ReceptionData.IsDemodLocked = true; is_status_update = true; break; case MSG_SMS_NO_SIGNAL_IND: sms_info("MSG_SMS_NO_SIGNAL_IND"); client->sms_stat_dvb.ReceptionData.IsDemodLocked = false; is_status_update = true; break; case MSG_SMS_TRANSMISSION_IND: { sms_info("MSG_SMS_TRANSMISSION_IND"); memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData, sizeof(struct TRANSMISSION_STATISTICS_S)); /* Mo need to correct guard interval * (as opposed to old statistics message). */ CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData); CORRECT_STAT_TRANSMISSON_MODE( client->sms_stat_dvb.TransmissionData); is_status_update = true; break; } case MSG_SMS_HO_PER_SLICES_IND: { struct RECEPTION_STATISTICS_S *pReceptionData = &client->sms_stat_dvb.ReceptionData; struct SRVM_SIGNAL_STATUS_S SignalStatusData; /*sms_info("MSG_SMS_HO_PER_SLICES_IND");*/ SignalStatusData.result = pMsgData[0]; SignalStatusData.snr = pMsgData[1]; SignalStatusData.inBandPower = (s32) pMsgData[2]; SignalStatusData.tsPackets = pMsgData[3]; SignalStatusData.etsPackets = pMsgData[4]; SignalStatusData.constellation = pMsgData[5]; SignalStatusData.hpCode = pMsgData[6]; SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03; SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03; SignalStatusData.cellId = pMsgData[9] & 0xFFFF; SignalStatusData.reason = pMsgData[10]; SignalStatusData.requestId = pMsgData[11]; pReceptionData->IsRfLocked = pMsgData[16]; pReceptionData->IsDemodLocked = pMsgData[17]; pReceptionData->ModemState = pMsgData[12]; pReceptionData->SNR = pMsgData[1]; pReceptionData->BER = pMsgData[13]; pReceptionData->RSSI = pMsgData[14]; CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData); pReceptionData->InBandPwr = (s32) pMsgData[2]; pReceptionData->CarrierOffset = (s32) pMsgData[15]; pReceptionData->TotalTSPackets = pMsgData[3]; pReceptionData->ErrorTSPackets = pMsgData[4]; /* TS PER */ if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets) > 0) { pReceptionData->TS_PER = (SignalStatusData.etsPackets * 100) / (SignalStatusData.tsPackets + SignalStatusData.etsPackets); } else { pReceptionData->TS_PER = 0; } pReceptionData->BERBitCount = pMsgData[18]; pReceptionData->BERErrorCount = pMsgData[19]; pReceptionData->MRC_SNR = pMsgData[20]; pReceptionData->MRC_InBandPwr = pMsgData[21]; pReceptionData->MRC_RSSI = pMsgData[22]; is_status_update = true; break; } case MSG_SMS_GET_STATISTICS_EX_RES: { struct RECEPTION_STATISTICS_S *pReceptionData = &client->sms_stat_dvb.ReceptionData; struct SMSHOSTLIB_STATISTICS_ISDBT_S *pStatsIsdbt; struct SRVM_SIGNAL_STATUS_S SignalStatusData; /*sms_info("MSG_SMS_GET_STATISTICS_EX_RES");*/ pMsgData++; pStatsIsdbt = (struct SMSHOSTLIB_STATISTICS_ISDBT_S*)pMsgData; /* sms_info("%d layers detected", pStatsIsdbt->NumOfLayers); sms_info("InBandPwr = %d dBm", pStatsIsdbt->InBandPwr); sms_info("SNR = %d dB", pStatsIsdbt->SNR); sms_info("RSSI = %d dBm", pStatsIsdbt->RSSI); */ /* update signal status */ SignalStatusData.snr = pStatsIsdbt->SNR; SignalStatusData.tsPackets = pStatsIsdbt->LayerInfo[0].TotalTSPackets; SignalStatusData.etsPackets = pStatsIsdbt->LayerInfo[0].ErrorTSPackets; SignalStatusData.constellation = pStatsIsdbt->LayerInfo[0].Constellation; SignalStatusData.inBandPower = pStatsIsdbt->InBandPwr; /* update reception data */ pReceptionData->IsRfLocked = pStatsIsdbt->IsRfLocked; pReceptionData->IsDemodLocked = pStatsIsdbt->IsDemodLocked; pReceptionData->ModemState = pStatsIsdbt->ModemState; pReceptionData->SNR = pStatsIsdbt->SNR; pReceptionData->BER = pStatsIsdbt->LayerInfo[0].BER; pReceptionData->BERErrorCount = pStatsIsdbt->LayerInfo[0].BERErrorCount; pReceptionData->BERBitCount = pStatsIsdbt->LayerInfo[0].BERBitCount; pReceptionData->RSSI = pStatsIsdbt->RSSI; CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData); pReceptionData->InBandPwr = pStatsIsdbt->InBandPwr; pReceptionData->CarrierOffset = pStatsIsdbt->CarrierOffset; pReceptionData->ErrorTSPackets = pStatsIsdbt->LayerInfo[0].ErrorTSPackets; pReceptionData->TotalTSPackets = pStatsIsdbt->LayerInfo[0].TotalTSPackets; /* TS PER */ if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets) > 0) { pReceptionData->TS_PER = (SignalStatusData.etsPackets * 100) / (SignalStatusData.tsPackets + SignalStatusData.etsPackets); } else { pReceptionData->TS_PER = 0; } /* pReceptionData->MRC_SNR = pReceptionData->MRC_InBandPwr = pReceptionData->MRC_RSSI = */ client->last_sample_time = jiffies_to_msecs(jiffies); is_status_update = true; complete(&client->get_stats_done); break; } } smscore_putbuffer(client->coredev, cb); if (is_status_update) { /* sms_info("client->fe_status = %d",client->fe_status); sms_info("--- TransmissionData ---"); sms_info(" Frequency %d", client->sms_stat_dvb.TransmissionData.Frequency); sms_info(" Constellation %d", client->sms_stat_dvb.TransmissionData.Constellation); sms_info(" IsDemodLocked %d", client->sms_stat_dvb.TransmissionData.IsDemodLocked); sms_info("--- ReceptionData ---"); sms_info(" IsDemodLocked %d", client->sms_stat_dvb.ReceptionData.IsDemodLocked); sms_info(" BER %d", client->sms_stat_dvb.ReceptionData.BER); sms_info(" ErrorTSPackets %d", client->sms_stat_dvb.ReceptionData.ErrorTSPackets); sms_info(" InBandPwr %d", client->sms_stat_dvb.ReceptionData.InBandPwr); sms_info(" IsRfLocked %d", client->sms_stat_dvb.ReceptionData.IsRfLocked); sms_info(" RSSI %d", client->sms_stat_dvb.ReceptionData.RSSI); sms_info(" SNR %d", client->sms_stat_dvb.ReceptionData.SNR); */ if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) { client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK); if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets == 0) sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK); else sms_board_dvb3_event(client, DVB3_EVENT_UNC_ERR); } else { /*client->fe_status = (phdr->msgType == MSG_SMS_NO_SIGNAL_IND) ? 0 : FE_HAS_SIGNAL;*/ client->fe_status = 0; sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK); } } return 0; }