Пример #1
0
int smsi2c_ts_feed(void *args, unsigned char * ts_buffer, int size) 
{
	struct smscore_device_t *coredev = (struct smscore_device_t *)args;
	struct smscore_buffer_t *cb;
	struct SmsMsgHdr_S *phdr;
	int len = 0;
	int quotient, residue;
	int ts_buf_size_188align;
	sms_debug("%s: buffer:0x%p, size:%d\n", __func__, ts_buffer, size);
if (!size || !args)
		return 0;

#define TS_PACKET_SIZE 188
	ts_buf_size_188align = rounddown((MAX_I2C_BUF_SIZE - sizeof(struct SmsMsgHdr_S)), TS_PACKET_SIZE);
	quotient = size / ts_buf_size_188align;
	residue = size % ts_buf_size_188align;

	for (; quotient > 0; quotient--) {
		cb = smscore_getbuffer(coredev);
		if (!cb) {
			sms_err("Unable to allocate data buffer!\n");
			goto exit;
		}
		phdr = (struct SmsMsgHdr_S *)cb->p;
		memset(cb->p, 0, (int)sizeof(struct SmsMsgHdr_S));
		SMS_INIT_MSG_EX(phdr, MSG_SMS_DAB_CHANNEL, HIF_TASK, 1, ts_buf_size_188align + sizeof(struct SmsMsgHdr_S));
		memcpy((u8*)(phdr+1),ts_buffer, ts_buf_size_188align);
		cb->offset = 0;
		cb->size = ts_buf_size_188align + sizeof(struct SmsMsgHdr_S);
		smscore_onresponse(coredev, cb);
		
		ts_buffer += ts_buf_size_188align;
		len += ts_buf_size_188align;
	}
	if (residue) {
		cb = smscore_getbuffer(coredev);
		if (!cb) {
			sms_err("Unable to allocate data buffer!\n");
			goto exit;
		}
		phdr = (struct SmsMsgHdr_S *)cb->p;
		memset(cb->p, 0, (int)sizeof(struct SmsMsgHdr_S));
		SMS_INIT_MSG_EX(phdr, MSG_SMS_DAB_CHANNEL, HIF_TASK, 1, residue + sizeof(struct SmsMsgHdr_S));
		memcpy((u8*)(phdr+1),ts_buffer, residue);
		cb->offset = 0;
		cb->size = residue + sizeof(struct SmsMsgHdr_S);
		smscore_onresponse(coredev, cb);
		
		ts_buffer += residue;
		len += residue;
	}
	
exit:
	return len;

}
Пример #2
0
struct _rx_buffer_st *allocate_rx_buf(void *context, int size)
{
	struct smscore_buffer_t *buf;
	struct _spi_device_st *spi_device = (struct _spi_device_st *) context;
	if (size > RX_BUFFER_SIZE) {
		PERROR("Requested size is bigger than max buffer size.\n");
		return NULL;
	}
	buf = smscore_getbuffer(spi_device->coredev);
	PDEBUG("Recieved Rx buf %p physical 0x%x (contained in %p)\n", buf->p,
	       buf->phys, buf);

	/* note: this is not mistake! the rx_buffer_st is identical to part of
	   smscore_buffer_t and we return the address of the start of the
	   identical part */
	return (struct _rx_buffer_st *) &buf->p;
}
Пример #3
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;
}
Пример #4
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);
}
Пример #5
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);
}
Пример #6
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);
}
Пример #7
0
static void smsi2c_worker_thread(void *args) 
{
	struct smscore_buffer_t *cb;
	struct SmsMsgHdr_S *phdr;
	u16 len;
	int ret;

	sms_debug("Worker thread is running.\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(cb->p, 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]);
	ret = i2c_master_recv(g_smsi2c_device->client, 
							cb->p, 
							(int)sizeof(struct SmsMsgHdr_S));
	if (ret < 0) {
		sms_err("Unable to read sms header! ret=%d\n", ret);
		goto exit;
	}

	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");
	len = phdr->msgLength;
	
	if (len > sizeof(struct SmsMsgHdr_S))
	{
		ret = i2c_master_recv(g_smsi2c_device->client, 
								(u8*)(phdr+1), 
								len - (int)sizeof(struct SmsMsgHdr_S));
		sms_debug("recv of data returned %d", ret);
		if (ret < 0) {
			sms_err("Unable to read sms payload!\n");
			goto exit;
		}
	}
	
	switch (phdr->msgType)
	{
		case MSG_SMS_GET_VERSION_EX_RES: 
		{
			struct SmsVersionRes_S *ver =
					(struct SmsVersionRes_S *) phdr;
			sms_debug("MSG_SMS_GET_VERSION_EX_RES "
					"id %d prots 0x%x ver %d.%d",
					ver->xVersion.FirmwareId,
					ver->xVersion.SupportedProtocols,
					ver->xVersion.RomVer.Major,
					ver->xVersion.RomVer.Minor);
			
			smscore_set_device_mode(g_smsi2c_device->coredev, 
					ver->xVersion.FirmwareId == 255 ?
					SMSHOSTLIB_DEVMD_NONE : ver->xVersion.FirmwareId);
			complete(&g_smsi2c_device->version_ex_done);
			break;
		}
	}
	sms_debug("Message recieved. Sending to callback.....\n");	
	cb->offset = 0;
	cb->size = len;
	smscore_onresponse(g_smsi2c_device->coredev, cb);
	
exit:
	return;
}