ssize_t bbd_sensor_write_internal(const char *sensorData, size_t size)
{
	int                       wr_size;
	struct bbd_buffer        *prxb    = NULL;
        struct bbd_sensor_device* ps = bbd_sensor_ptr();
        struct bbd_base*          p  = bbd_sensor_ptr_base();

	if (!p || !ps)
		return -EINVAL;

	dprint("%s[%d]\n", __func__, (int) size);

	prxb = &p->rxb;

	mutex_lock(&prxb->lock);

	wr_size = MIN((BBD_MAX_DATA_SIZE - prxb->buff_size), size);
        memcpy(prxb->pbuff + prxb->buff_size, sensorData, wr_size);
        prxb->buff_size += wr_size;
	prxb->count += wr_size;
        bbd_sensor_write_handshake(ps, prxb); 

	mutex_unlock(&prxb->lock);

	return wr_size;
}
ssize_t bbd_sensor_write(struct file        *filp,
			const char __user   *buf,
			size_t size, loff_t *ppos)
{
	int                       wr_size = MIN(BBD_MAX_DATA_SIZE, size);
	struct bbd_buffer        *prxb    = NULL;
        struct bbd_sensor_device* ps = bbd_sensor_ptr();
        struct bbd_base*          p  = bbd_sensor_ptr_base();

	if (!p || !ps)
		return -EINVAL;

	dprint("%s[%d]\n", __func__, (int) size);

	prxb = &p->rxb;

	mutex_lock(&prxb->lock);
	if (copy_from_user(prxb->pbuff, buf, wr_size)) {
		wr_size = -EFAULT;
        }
        else {
		prxb->buff_size = wr_size;
		bbd_sensor_write_handshake(ps, prxb); 
        }
	mutex_unlock(&prxb->lock);
	return wr_size;
}
/**
 * pull packet from rx_list buffer directly
 *
 * @pbuff: buffer pointer
 * @len  : length of pulling data
 * @timeout_ms: timeout for waiting data in rx_list buffer
 *              if timeout_ms is 0, pull one packet from rx_list buffer directly
 *
 * @return: length of buffer, -ETIMEDOUT = timeout
 */
ssize_t bbd_pull_packet(unsigned char *pbuff,
			size_t         len,
			unsigned int   timeout_ms)
{
	struct bbd_buffer *prxb = NULL;
	int pull_size = 0;
	int timeout = 0;
        struct bbd_base* p = bbd_sensor_ptr_base();

	if (!p || pbuff == NULL)
		return -EINVAL;

	prxb = &p->rxb;
#if 0
	//If SSP wants to wait for data and starts read, buff_size can be 0.
	//So, we should remove following if() clause
	if (prxb->buff_size <= 0) {
		printk("error : prxb->buff_size = %d\n", prxb->buff_size);
		return prxb->buff_size;
	}
#endif
	if (timeout_ms) {
		timeout = wait_event_interruptible_timeout(
						prxb->poll_inq,
						(prxb->buff_size > 0),
						msecs_to_jiffies(timeout_ms));
		if (!timeout) {
			//Following line is bug, we should NEVER set buff_size to invalid value like errno. It's bad hack.
			//prxb->buff_size = -ETIMEDOUT;
			prxb->buff_size = 0;
			return -ETIMEDOUT;
		}
	}

	mutex_lock(&prxb->lock);
	pull_size = MIN(prxb->buff_size, len);
	memcpy(pbuff, prxb->pbuff, pull_size);
	prxb->buff_size -= pull_size;

	//shift. TODO: circ buf
	{
		unsigned char *top =  prxb->pbuff + pull_size;
		memcpy(prxb->pbuff, top, prxb->buff_size);
	}
	mutex_unlock(&prxb->lock);

	wake_up(&prxb->comp_inq);

	return pull_size;
}
/**
 * pull packet from rx_list buffer directly
 *
 * @pbuff: buffer pointer
 * @len  : length of pulling data
 * @timeout_ms: timeout for waiting data in rx_list buffer
 *              if timeout_ms is 0, pull one packet from rx_list buffer directly
 *
 * @return: length of buffer, -ETIMEDOUT = timeout
 */
ssize_t bbd_pull_packet(unsigned char *pbuff,
			size_t         len,
			unsigned int   timeout_ms)
{
	struct bbd_buffer *prxb = NULL;
	int pull_size = 0;
	int timeout = 0;
        struct bbd_base* p = bbd_sensor_ptr_base();

	if (!p || pbuff == NULL)
		return -EINVAL;

	prxb = &p->rxb;

	if (prxb->buff_size <= 0) {
		dprint("error : prxb->buff_size = %d\n", prxb->buff_size);
		return prxb->buff_size;
	}

	if (timeout_ms) {
		timeout = wait_event_interruptible_timeout(
						prxb->poll_inq,
						(prxb->buff_size > 0),
						msecs_to_jiffies(timeout_ms));
		if (!timeout) {
			dprint("error : timeout for prx->poll_inq\n");
			prxb->buff_size = -ETIMEDOUT;
			return -ETIMEDOUT;
		}
	}

	mutex_lock(&prxb->lock);
	pull_size = MIN(prxb->buff_size, len);
	memcpy(pbuff, prxb->pbuff, pull_size);
	prxb->buff_size -= pull_size;

	//shift. TODO: circ buf
	{
		unsigned char *top =  prxb->pbuff + pull_size;
		memcpy(prxb->pbuff, top, prxb->buff_size);
	}
	mutex_unlock(&prxb->lock);

	wake_up(&prxb->comp_inq);

	return pull_size;
}