Example #1
0
/**
 * 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);
	}
}
Example #2
0
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;
}
Example #4
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;
}
Example #5
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;
}
Example #6
0
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);
}
Example #7
0
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;
}
Example #9
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);
}
Example #10
0
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);
}
Example #11
0
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;
}
Example #12
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);
}
Example #13
0
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;
}