Exemple #1
0
/*  Modem_request command */
static int lge_dm_tty_modem_request(struct dm_tty *lge_dm_tty_drv, const unsigned char *buf, int count)
{

	short modem_chip = Primary_modem_chip;
	int length;

	if(lge_dm_tty_drv->logging_mode == DM_APP_SDM)
	{
		length = dm_modem_request_header_length + sizeof(modem_chip);

		if (modem_chip == Primary_modem_chip) {
			/* send masks to modem */
			if(buf != NULL)
				diag_process_hdlc((void *)buf + length, count - length);
			else
				pr_info("[DM_APP]buf is null , lge_dm_tty_modem_request \n");
		} else if (modem_chip == Secondary_modem_chip) {

			/* send masks to 9k */
			//TBD

		} else {
			pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_write"
				"modem_number %d "
				"error count = %d length = %d\n",
				__func__, modem_chip, count, length);
		}
	}
	else if(lge_dm_tty_drv->logging_mode == DM_APP_ODM)
	{
		diag_process_hdlc((void *)buf, count);
	}

	return count;
}
void diag_process_hdlc_fn(struct work_struct *work)
{
	APPEND_DEBUG('D');
	diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
	diag_read_work_fn(work);
	APPEND_DEBUG('E');
}
/*  Modem_request command */
static int lge_dm_tty_modem_request(const unsigned char *buf, int count)
{
	short modem_chip = 0;
	int length = 0;

	memcpy(&modem_chip, buf + dm_modem_request_header_length,
							sizeof(modem_chip));

	length = dm_modem_request_header_length + sizeof(modem_chip);

	if (modem_chip == Primary_modem_chip) {
		/* send masks to modem */
		diag_process_hdlc((void *)buf + length, count - length);
	} else if (modem_chip == Secondary_modem_chip) {

		/* send masks to 9k */
		//TBD

	} else {
		pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_write"
			"modem_number %d "
			"error count = %d length = %d\n",
			__func__, modem_chip, count, length);
	}

	return count;
}
Exemple #4
0
void lge_dm_dload_fn(struct work_struct *work)
{

#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
    short modem_chip = Secondary_modem_chip;
    int err = 0;
    int index = 0;
#else
    short modem_chip = Primary_modem_chip;
#endif /*CONFIG_DIAGFWD_BRIDGE_CODE*/

    int count = 0, length = 0;
    int size = sizeof(empty_mask_buff)/sizeof(char);
    char mask_buf[20];

    while (count < size) {
        mask_buf[length++] = empty_mask_buff[count];
        if (empty_mask_buff[count] == CONTROL_CHAR) {
            if (modem_chip == Primary_modem_chip) {
                diag_process_hdlc((unsigned char *)mask_buf, length);
            } else if (modem_chip == Secondary_modem_chip) {
#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
                /* send masks to All 9k */
                for (index = 0; index < MAX_HSIC_DATA_CH; index++) {
                    if (diag_hsic[index].hsic_ch && (count > 0)){
                        /* wait sending mask updates
                         * if HSIC ch not ready */
                        if (diag_hsic[index].in_busy_hsic_write)
                            wait_event_interruptible(driver->wait_q,
                                (diag_hsic[index].
                                 in_busy_hsic_write != 1));
                        diag_hsic[index].in_busy_hsic_write = 1;
                        diag_hsic[index].in_busy_hsic_read_on_device =
                                            0;
                        err = diag_bridge_write(index, (unsigned char *)mask_buf, length);

                        if (err) {
                            pr_err("diag: err sending mask to MDM: %d\n",
                                   err);
                            /*
                            * If the error is recoverable, then
                            * clear the write flag, so we will
                            * resubmit a write on the next frame.
                            * Otherwise, don't resubmit a write
                            * on the next frame.
                            */
                            if ((-ESHUTDOWN) != err)
                                diag_hsic[index].in_busy_hsic_write = 0;
                         }
                     }
                }
#endif /*CONFIG_DIAGFWD_BRIDGE_CODE*/
            }
            length = 0;
        }
        count++;
    }
}
/*  Modem_request command */
static int lge_dm_dev_tty_modem_request(const unsigned char *buf, int count)
{
    /* send masks to modem */
    diag_process_hdlc((void *)buf, count);
//		pr_info(DM_DEV_TTY_MODULE_NAME ": %s:"
//		     "count = %d\n",__func__, count);

#if 0
    else {
void diag_read_work_fn(struct work_struct *work)
{
	APPEND_DEBUG('d');
	diag_process_hdlc(driver->usb_buf_out, driver->read_len);
	driver->usb_read_ptr->buf = driver->usb_buf_out;
	driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
	APPEND_DEBUG('e');
	diag_read(driver->usb_read_ptr);
	APPEND_DEBUG('f');
}
/*  Modem_request command */
static int lge_dm_tty_modem_request(const unsigned char *buf, int count)
{
	short modem_chip;
	int length;

	memcpy(&modem_chip, buf + dm_modem_request_header_length,
							sizeof(modem_chip));

	length = dm_modem_request_header_length + sizeof(modem_chip);

	if (modem_chip == Primary_modem_chip) {
		/* send masks to modem */
		diag_process_hdlc((void *)buf + length, count - length);
	} else if (modem_chip == Secondary_modem_chip) {

#ifdef CONFIG_DIAG_SDIO_PIPE
		/* send masks to 9k */
		if (driver->sdio_ch) {
			wait_event_interruptible(driver->wait_q,
				(sdio_write_avail(driver->sdio_ch)
					>= (count - length)));
			if (driver->sdio_ch && ((count - length) > 0)) {
				sdio_write(driver->sdio_ch,
					(void *)buf + length,
						count - length);
			}
		}
#endif

	} else {
		pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_write"
			"modem_number %d "
			"error count = %d length = %d\n",
			__func__, modem_chip, count, length);
	}

	return count;
}
static int diagchar_write(struct file *file, const char __user *buf,
			      size_t count, loff_t *ppos)
{
	int err, ret = 0, pkt_type;
#ifdef DIAG_DEBUG
	int length = 0, i;
#endif
	struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
	struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
	void *buf_copy = NULL;
	int payload_size;
#ifdef CONFIG_DIAG_OVER_USB
	if (((driver->logging_mode == USB_MODE) && (!driver->usb_connected)) ||
				(driver->logging_mode == NO_LOGGING_MODE)) {
		/*Drop the diag payload */
		return -EIO;
	}
#endif /* DIAG over USB */
	/* Get the packet type F3/log/event/Pkt response */
	err = copy_from_user((&pkt_type), buf, 4);
	/* First 4 bytes indicate the type of payload - ignore these */
	payload_size = count - 4;

	if (pkt_type == USER_SPACE_LOG_TYPE) {
		err = copy_from_user(driver->user_space_data, buf + 4,
							 payload_size);
		/* Check masks for On-Device logging */
		if (driver->mask_check) {
			if (!mask_request_validate(driver->user_space_data)) {
				pr_alert("diag: mask request Invalid\n");
				return -EFAULT;
			}
		}
		buf = buf + 4;
#ifdef DIAG_DEBUG
		pr_debug("diag: user space data %d\n", payload_size);
		for (i = 0; i < payload_size; i++)
			pr_debug("\t %x", *((driver->user_space_data)+i));
#endif
#ifdef CONFIG_DIAG_SDIO_PIPE
		/* send masks to 9k too */
		if (driver->sdio_ch) {
			wait_event_interruptible(driver->wait_q,
				 (sdio_write_avail(driver->sdio_ch) >=
					 payload_size));
			if (driver->sdio_ch && (payload_size > 0)) {
				sdio_write(driver->sdio_ch, (void *)
				   (driver->user_space_data), payload_size);
			}
		}
#endif
		/* send masks to modem now */
		diag_process_hdlc((void *)(driver->user_space_data),
							 payload_size);
		return 0;
	}

	buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY);
	if (!buf_copy) {
		driver->dropped_count++;
		return -ENOMEM;
	}

	err = copy_from_user(buf_copy, buf + 4, payload_size);
	if (err) {
		printk(KERN_INFO "diagchar : copy_from_user failed\n");
		ret = -EFAULT;
		goto fail_free_copy;
	}
#ifdef DIAG_DEBUG
	printk(KERN_DEBUG "data is -->\n");
	for (i = 0; i < payload_size; i++)
		printk(KERN_DEBUG "\t %x \t", *(((unsigned char *)buf_copy)+i));
#endif
	send.state = DIAG_STATE_START;
	send.pkt = buf_copy;
	send.last = (void *)(buf_copy + payload_size - 1);
	send.terminate = 1;
#ifdef DIAG_DEBUG
	pr_debug("diag: Already used bytes in buffer %d, and"
	" incoming payload size is %d\n", driver->used, payload_size);
	printk(KERN_DEBUG "hdlc encoded data is -->\n");
	for (i = 0; i < payload_size + 8; i++) {
		printk(KERN_DEBUG "\t %x \t", *(((unsigned char *)buf_hdlc)+i));
		if (*(((unsigned char *)buf_hdlc)+i) != 0x7e)
			length++;
	}
#endif
	mutex_lock(&driver->diagchar_mutex);
	if (!buf_hdlc)
		buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
						 POOL_TYPE_HDLC);
	if (!buf_hdlc) {
		ret = -ENOMEM;
		goto fail_free_hdlc;
	}
	if (HDLC_OUT_BUF_SIZE - driver->used <= (2*payload_size) + 3) {
		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
		if (err) {
			/*Free the buffer right away if write failed */
			diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
			diagmem_free(driver, (unsigned char *)driver->
				 write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
			ret = -EIO;
			goto fail_free_hdlc;
		}
		buf_hdlc = NULL;
		driver->used = 0;
		buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
							 POOL_TYPE_HDLC);
		if (!buf_hdlc) {
			ret = -ENOMEM;
			goto fail_free_hdlc;
		}
	}

	enc.dest = buf_hdlc + driver->used;
	enc.dest_last = (void *)(buf_hdlc + driver->used + 2*payload_size + 3);
	diag_hdlc_encode(&send, &enc);

	/* This is to check if after HDLC encoding, we are still within the
	 limits of aggregation buffer. If not, we write out the current buffer
	and start aggregation in a newly allocated buffer */
	if ((unsigned int) enc.dest >=
		 (unsigned int)(buf_hdlc + HDLC_OUT_BUF_SIZE)) {
		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
		if (err) {
			/*Free the buffer right away if write failed */
			diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
			diagmem_free(driver, (unsigned char *)driver->
				 write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
			ret = -EIO;
			goto fail_free_hdlc;
		}
		buf_hdlc = NULL;
		driver->used = 0;
		buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
							 POOL_TYPE_HDLC);
		if (!buf_hdlc) {
			ret = -ENOMEM;
			goto fail_free_hdlc;
		}
		enc.dest = buf_hdlc + driver->used;
		enc.dest_last = (void *)(buf_hdlc + driver->used +
							 (2*payload_size) + 3);
		diag_hdlc_encode(&send, &enc);
	}

	driver->used = (uint32_t) enc.dest - (uint32_t) buf_hdlc;
	if (pkt_type == DATA_TYPE_RESPONSE) {
		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
		if (err) {
			/*Free the buffer right away if write failed */
			diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
			diagmem_free(driver, (unsigned char *)driver->
				 write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
			ret = -EIO;
			goto fail_free_hdlc;
		}
		buf_hdlc = NULL;
		driver->used = 0;
	}

	mutex_unlock(&driver->diagchar_mutex);
	diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
	if (!timer_in_progress)	{
		timer_in_progress = 1;
		ret = mod_timer(&drain_timer, jiffies + msecs_to_jiffies(500));
	}
	return 0;

fail_free_hdlc:
	buf_hdlc = NULL;
	driver->used = 0;
	diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
	mutex_unlock(&driver->diagchar_mutex);
	return ret;

fail_free_copy:
	diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
	return ret;
}
/*  Modem_request command */
static int lge_dm_tty_modem_request(struct dm_tty *lge_dm_tty_drv, const unsigned char *buf, int count)
{

	int length;
	
#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
	short modem_chip = Secondary_modem_chip;
	int err = 0;
	int index = 0;
#else
	short modem_chip = Primary_modem_chip;
#endif /*CONFIG_DIAGFWD_BRIDGE_CODE*/	


	if(lge_dm_tty_drv->logging_mode == DM_APP_SDM)
	{
	length = dm_modem_request_header_length + sizeof(modem_chip);

	if (modem_chip == Primary_modem_chip) {
		/* send masks to modem */
		if(buf != NULL)
		diag_process_hdlc((void *)buf + length, count - length);
		else
			pr_info("[DM_APP]buf is null , lge_dm_tty_modem_request \n");
	} else if (modem_chip == Secondary_modem_chip) {
	
		/* send masks to 9k */
#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
				/* send masks to All 9k */
				for (index = 0; index < MAX_HSIC_CH; index++) {
		//			if (diag_hsic[index].hsic_ch && (payload_size > 0) &&
		//							 (remote_proc == MDM)) {
					if (diag_hsic[index].hsic_ch && (count > 0)){
						/* wait sending mask updates
						 * if HSIC ch not ready */
						if (diag_hsic[index].in_busy_hsic_write)
							wait_event_interruptible(driver->wait_q,
								(diag_hsic[index].
								 in_busy_hsic_write != 1));
						diag_hsic[index].in_busy_hsic_write = 1;
						diag_hsic[index].in_busy_hsic_read_on_device =
											0;
		//				err = diag_bridge_write(index,
		//						driver->user_space_data +
		//						token_offset, payload_size);
						err = diag_bridge_write(index, (void *)buf + length, count - length);
		
						if (err) {
							pr_err("diag: err sending mask to MDM: %d\n",
								   err);
							/*
							* If the error is recoverable, then
							* clear the write flag, so we will
							* resubmit a write on the next frame.
							* Otherwise, don't resubmit a write
							* on the next frame.
							*/
							if ((-ESHUTDOWN) != err)
								diag_hsic[index].in_busy_hsic_write = 0;
						 }
					 }
				}
		
#endif /*CONFIG_DIAGFWD_BRIDGE_CODE*/

		} else {
			pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_write"
				"modem_number %d "
				"error count = %d length = %d\n",
				__func__, modem_chip, count, length);
		}
	}
	else if(lge_dm_tty_drv->logging_mode == DM_APP_ODM)
	{
		if (modem_chip == Primary_modem_chip) {
			diag_process_hdlc((void *)buf, count);
		} else if (modem_chip == Secondary_modem_chip) {
#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
				/* send masks to All 9k */
				for (index = 0; index < MAX_HSIC_CH; index++) {
		//			if (diag_hsic[index].hsic_ch && (payload_size > 0) &&
		//							 (remote_proc == MDM)) {
					if (diag_hsic[index].hsic_ch && (count > 0)){
						/* wait sending mask updates
						 * if HSIC ch not ready */
						if (diag_hsic[index].in_busy_hsic_write)
							wait_event_interruptible(driver->wait_q,
								(diag_hsic[index].
								 in_busy_hsic_write != 1));
						diag_hsic[index].in_busy_hsic_write = 1;
						diag_hsic[index].in_busy_hsic_read_on_device =
											0;
		//				err = diag_bridge_write(index,
		//						driver->user_space_data +
		//						token_offset, payload_size);
//						err = diag_bridge_write(index, (void *)buf + length, count - length);
						err = diag_bridge_write(index, (void *)buf, count);
		
						if (err) {
							pr_err("diag: err sending mask to MDM: %d\n",
								   err);
							/*
							* If the error is recoverable, then
							* clear the write flag, so we will
							* resubmit a write on the next frame.
							* Otherwise, don't resubmit a write
							* on the next frame.
							*/
							if ((-ESHUTDOWN) != err)
								diag_hsic[index].in_busy_hsic_write = 0;
						 }
					 }
				}
		
#endif /*CONFIG_DIAGFWD_BRIDGE_CODE*/
		}
	}

	return count;
}
static int diagchar_write(struct file *file, const char __user *buf,
			      size_t count, loff_t *ppos)
{
	int err, ret = 0, pkt_type;
#ifdef DIAG_DEBUG
	int length = 0, i;
#endif
	struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
	struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
	void *buf_copy = NULL;
	int payload_size;
	unsigned char is_encoded = 0;
	void *large_buf_hdlc;

#ifdef CONFIG_DIAG_OVER_USB
	if (((driver->logging_mode == USB_MODE) && (!driver->usb_connected)) ||
				(driver->logging_mode == NO_LOGGING_MODE)) {
		/*Drop the diag payload */
		return -EIO;
	}
#endif /* DIAG over USB */
	/* Get the packet type F3/log/event/Pkt response */
	err = copy_from_user((&pkt_type), buf, 4);
	/*First 4 bytes indicate the type of payload - ignore these */
	payload_size = count - 4;

	if(pkt_type == -3) { //-DIAG_DATA_TYPE_RESPONSE => no hdlc encode
		is_encoded = 1;
	} else { 
		is_encoded = 0;
	}

	if(is_encoded) {
		large_buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE, POOL_TYPE_HDLC);
		if (!large_buf_hdlc) {
			driver->dropped_count++;
			return -ENOMEM;
		}

		err = copy_from_user(large_buf_hdlc, buf + 4, payload_size);
		if (err) {
			diagmem_free(driver, large_buf_hdlc, POOL_TYPE_HDLC);
			printk(KERN_INFO "diagchar : copy_from_user failed \n");
			ret = -EFAULT;
			return ret;
		}

		mutex_lock(&driver->diagchar_mutex);
		driver->write_ptr_svc = (struct diag_request *)
			(diagmem_alloc(driver, sizeof(struct diag_request),
				 POOL_TYPE_WRITE_STRUCT));
		driver->write_ptr_svc->buf = large_buf_hdlc;
		driver->used = payload_size; 
		driver->write_ptr_svc->length = driver->used;

		err = usb_diag_write(driver->legacy_ch, driver->write_ptr_svc);
		if (err) {
			printk(KERN_INFO "\n size written length[%d] error[%d] \n", driver->used, err);
			diagmem_free(driver, large_buf_hdlc, POOL_TYPE_HDLC);
			ret = -EIO;
			mutex_unlock(&driver->diagchar_mutex);
			return -EIO;
		}
#ifdef DIAG_DEBUG
		printk(KERN_INFO "\n LARGE_size written is %d \n", driver->used);
#endif
		driver->used = 0;
		mutex_unlock(&driver->diagchar_mutex);
		return 0;
	}

	if (pkt_type == MEMORY_DEVICE_LOG_TYPE) {
		if (!mask_request_validate((unsigned char *)buf)) {
			printk(KERN_ALERT "mask request Invalid ..cannot send to modem \n");
			return -EFAULT;
		}
		buf = buf + 4;
#ifdef DIAG_DEBUG
		printk(KERN_INFO "\n I got the masks: %d\n", payload_size);
		for (i = 0; i < payload_size; i++)
			printk(KERN_DEBUG "\t %x", *(((unsigned char *)buf)+i));
#endif
		diag_process_hdlc((void *)buf, payload_size);
		return 0;
	}

	buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY);
	if (!buf_copy) {
		driver->dropped_count++;
		return -ENOMEM;
	}

	err = copy_from_user(buf_copy, buf + 4, payload_size);
	if (err) {
		printk(KERN_INFO "diagchar : copy_from_user failed\n");
		ret = -EFAULT;
		goto fail_free_copy;
	}
#ifdef DIAG_DEBUG
	printk(KERN_DEBUG "data is -->\n");
	for (i = 0; i < payload_size; i++)
		printk(KERN_DEBUG "\t %x \t", *(((unsigned char *)buf_copy)+i));
#endif
	send.state = DIAG_STATE_START;
	send.pkt = buf_copy;
	send.last = (void *)(buf_copy + payload_size - 1);
	send.terminate = 1;
#ifdef DIAG_DEBUG
	printk(KERN_INFO "\n Already used bytes in buffer %d, and"
	" incoming payload size is %d\n", driver->used, payload_size);
	printk(KERN_DEBUG "hdlc encoded data is -->\n");
	for (i = 0; i < payload_size + 8; i++) {
		printk(KERN_DEBUG "\t %x \t", *(((unsigned char *)buf_hdlc)+i));
		if (*(((unsigned char *)buf_hdlc)+i) != 0x7e)
			length++;
	}
#endif
	mutex_lock(&driver->diagchar_mutex);
	if (!buf_hdlc)
		buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
						 POOL_TYPE_HDLC);
	if (!buf_hdlc) {
		ret = -ENOMEM;
		goto fail_free_hdlc;
	}
	if (HDLC_OUT_BUF_SIZE - driver->used <= (2*payload_size) + 3) {
		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
		if (err) {
			/*Free the buffer right away if write failed */
			diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
			diagmem_free(driver, (unsigned char *)driver->
				 write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
			ret = -EIO;
			goto fail_free_hdlc;
		}
		buf_hdlc = NULL;
#ifdef DIAG_DEBUG
		printk(KERN_INFO "\n size written is %d\n", driver->used);
#endif
		driver->used = 0;
		buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
							 POOL_TYPE_HDLC);
		if (!buf_hdlc) {
			ret = -ENOMEM;
			goto fail_free_hdlc;
		}
	}

	enc.dest = buf_hdlc + driver->used;
	enc.dest_last = (void *)(buf_hdlc + driver->used + 2*payload_size + 3);
	diag_hdlc_encode(&send, &enc);

	/* This is to check if after HDLC encoding, we are still within the
	 limits of aggregation buffer. If not, we write out the current buffer
	and start aggregation in a newly allocated buffer */
	if ((unsigned int) enc.dest >=
		 (unsigned int)(buf_hdlc + HDLC_OUT_BUF_SIZE)) {
		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
		if (err) {
			/*Free the buffer right away if write failed */
			diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
			diagmem_free(driver, (unsigned char *)driver->
				 write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
			ret = -EIO;
			goto fail_free_hdlc;
		}
		buf_hdlc = NULL;
#ifdef DIAG_DEBUG
		printk(KERN_INFO "\n size written is %d\n", driver->used);
#endif
		driver->used = 0;
		buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
							 POOL_TYPE_HDLC);
		if (!buf_hdlc) {
			ret = -ENOMEM;
			goto fail_free_hdlc;
		}
		enc.dest = buf_hdlc + driver->used;
		enc.dest_last = (void *)(buf_hdlc + driver->used +
							 (2*payload_size) + 3);
		diag_hdlc_encode(&send, &enc);
	}

	driver->used = (uint32_t) enc.dest - (uint32_t) buf_hdlc;
	if (pkt_type == DATA_TYPE_RESPONSE) {
		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
		if (err) {
			/*Free the buffer right away if write failed */
			diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
			diagmem_free(driver, (unsigned char *)driver->
				 write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
			ret = -EIO;
			goto fail_free_hdlc;
		}
		buf_hdlc = NULL;
#ifdef DIAG_DEBUG
		printk(KERN_INFO "\n size written is %d\n", driver->used);
#endif
		driver->used = 0;
	}

	mutex_unlock(&driver->diagchar_mutex);
	diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
	if (!timer_in_progress)	{
		timer_in_progress = 1;
		ret = mod_timer(&drain_timer, jiffies + msecs_to_jiffies(500));
	}
	return 0;

fail_free_hdlc:
	buf_hdlc = NULL;
	driver->used = 0;
	diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
	mutex_unlock(&driver->diagchar_mutex);
	return ret;

fail_free_copy:
	diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
	return ret;
}
static int diagchar_write(struct file *file, const char __user *buf,
			      size_t count, loff_t *ppos)
{
	int err, ret = 0, pkt_type;

#ifdef CONFIG_LGE_DM_APP
	char *buf_cmp;
#endif

#ifdef DIAG_DEBUG
	int length = 0, i;
#endif
	struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
	struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
	void *buf_copy = NULL;
	int payload_size;
#ifdef CONFIG_DIAG_OVER_USB
	if (((driver->logging_mode == USB_MODE) && (!driver->usb_connected)) ||
				(driver->logging_mode == NO_LOGGING_MODE)) {
		/*Drop the diag payload */
		return -EIO;
	}
#endif /* DIAG over USB */
	/* Get the packet type F3/log/event/Pkt response */
	err = copy_from_user((&pkt_type), buf, 4);
	/* First 4 bytes indicate the type of payload - ignore these */
	payload_size = count - 4;

#ifdef CONFIG_LGE_DM_APP
	if (driver->logging_mode == DM_APP_MODE) {
		/* only diag cmd #250 for supporting testmode tool */
		buf_cmp = (char *)buf + 4;
		if (*(buf_cmp) != 0xFA)
			return 0;
	}
#endif

	if (payload_size > USER_SPACE_DATA) {
		pr_err("diag: Dropping packet, packet payload size crosses 8KB limit. Current payload size %d\n",
				payload_size);
		driver->dropped_count++;
		return -EBADMSG;
	}
	if (pkt_type == DCI_DATA_TYPE) {
		err = copy_from_user(driver->user_space_data, buf + 4,
							 payload_size);
		if (err) {
			pr_alert("diag: copy failed for DCI data\n");
			return DIAG_DCI_SEND_DATA_FAIL;
		}
		err = diag_process_dci_client(driver->user_space_data,
							payload_size);
		return err;
	}
	if (pkt_type == USER_SPACE_LOG_TYPE) {
		err = copy_from_user(driver->user_space_data, buf + 4,
							 payload_size);
		/* Check masks for On-Device logging */
		if (driver->mask_check) {
			if (!mask_request_validate(driver->user_space_data)) {
				pr_alert("diag: mask request Invalid\n");
				return -EFAULT;
			}
		}
		buf = buf + 4;
#ifdef DIAG_DEBUG
		pr_debug("diag: user space data %d\n", payload_size);
		for (i = 0; i < payload_size; i++)
			pr_debug("\t %x", *((driver->user_space_data)+i));
#endif
#ifdef CONFIG_DIAG_SDIO_PIPE
		/* send masks to 9k too */
		if (driver->sdio_ch) {
			wait_event_interruptible(driver->wait_q,
				 (sdio_write_avail(driver->sdio_ch) >=
					 payload_size));
			if (driver->sdio_ch && (payload_size > 0)) {
				sdio_write(driver->sdio_ch, (void *)
				   (driver->user_space_data), payload_size);
			}
		}
#endif
#ifdef CONFIG_DIAG_BRIDGE_CODE
		/* send masks to 9k too */
		if (driver->hsic_ch && (payload_size > 0)) {
			/* wait sending mask updates if HSIC ch not ready */
			if (driver->in_busy_hsic_write)
				wait_event_interruptible(driver->wait_q,
					(driver->in_busy_hsic_write != 1));
			driver->in_busy_hsic_write = 1;
			driver->in_busy_hsic_read_on_device = 0;
			err = diag_bridge_write(driver->user_space_data,
							 payload_size);
			if (err) {
				pr_err("diag: err sending mask to MDM: %d\n",
									 err);
				/*
				* If the error is recoverable, then clear
				* the write flag, so we will resubmit a
				* write on the next frame.  Otherwise, don't
				* resubmit a write on the next frame.
				*/
				if ((-ESHUTDOWN) != err)
					driver->in_busy_hsic_write = 0;
			}
		}
#endif
		/* send masks to 8k now */
		diag_process_hdlc((void *)(driver->user_space_data),
							 payload_size);
		return 0;
	}

	if (payload_size > itemsize) {
		pr_err("diag: Dropping packet, packet payload size crosses"
				"4KB limit. Current payload size %d\n",
				payload_size);
		driver->dropped_count++;
		return -EBADMSG;
	}

	buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY);
	if (!buf_copy) {
		driver->dropped_count++;
		return -ENOMEM;
	}

	err = copy_from_user(buf_copy, buf + 4, payload_size);
	if (err) {
		printk(KERN_INFO "diagchar : copy_from_user failed\n");
		ret = -EFAULT;
		goto fail_free_copy;
	}
#ifdef DIAG_DEBUG
	printk(KERN_DEBUG "data is -->\n");
	for (i = 0; i < payload_size; i++)
		printk(KERN_DEBUG "\t %x \t", *(((unsigned char *)buf_copy)+i));
#endif
	send.state = DIAG_STATE_START;
	send.pkt = buf_copy;
	send.last = (void *)(buf_copy + payload_size - 1);
	send.terminate = 1;
#ifdef DIAG_DEBUG
	pr_debug("diag: Already used bytes in buffer %d, and"
	" incoming payload size is %d\n", driver->used, payload_size);
	printk(KERN_DEBUG "hdlc encoded data is -->\n");
	for (i = 0; i < payload_size + 8; i++) {
		printk(KERN_DEBUG "\t %x \t", *(((unsigned char *)buf_hdlc)+i));
		if (*(((unsigned char *)buf_hdlc)+i) != 0x7e)
			length++;
	}
#endif
	mutex_lock(&driver->diagchar_mutex);
	if (!buf_hdlc)
		buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
						 POOL_TYPE_HDLC);
	if (!buf_hdlc) {
		ret = -ENOMEM;
		goto fail_free_hdlc;
	}
	if (HDLC_OUT_BUF_SIZE - driver->used <= (2*payload_size) + 3) {
		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
		if (err) {
			/*Free the buffer right away if write failed */
			diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
			diagmem_free(driver, (unsigned char *)driver->
				 write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
			ret = -EIO;
			goto fail_free_hdlc;
		}
		buf_hdlc = NULL;
		driver->used = 0;
		buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
							 POOL_TYPE_HDLC);
		if (!buf_hdlc) {
			ret = -ENOMEM;
			goto fail_free_hdlc;
		}
	}

	enc.dest = buf_hdlc + driver->used;
	enc.dest_last = (void *)(buf_hdlc + driver->used + 2*payload_size + 3);
	diag_hdlc_encode(&send, &enc);

	/* This is to check if after HDLC encoding, we are still within the
	 limits of aggregation buffer. If not, we write out the current buffer
	and start aggregation in a newly allocated buffer */
	if ((unsigned int) enc.dest >=
		 (unsigned int)(buf_hdlc + HDLC_OUT_BUF_SIZE)) {
		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
		if (err) {
			/*Free the buffer right away if write failed */
			diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
			diagmem_free(driver, (unsigned char *)driver->
				 write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
			ret = -EIO;
			goto fail_free_hdlc;
		}
		buf_hdlc = NULL;
		driver->used = 0;
		buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
							 POOL_TYPE_HDLC);
		if (!buf_hdlc) {
			ret = -ENOMEM;
			goto fail_free_hdlc;
		}
		enc.dest = buf_hdlc + driver->used;
		enc.dest_last = (void *)(buf_hdlc + driver->used +
							 (2*payload_size) + 3);
		diag_hdlc_encode(&send, &enc);
	}

	driver->used = (uint32_t) enc.dest - (uint32_t) buf_hdlc;
	if (pkt_type == DATA_TYPE_RESPONSE) {
		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
		if (err) {
			/*Free the buffer right away if write failed */
			diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
			diagmem_free(driver, (unsigned char *)driver->
				 write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
			ret = -EIO;
			goto fail_free_hdlc;
		}
		buf_hdlc = NULL;
		driver->used = 0;
	}

	mutex_unlock(&driver->diagchar_mutex);
	diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
	if (!timer_in_progress)	{
		timer_in_progress = 1;
		ret = mod_timer(&drain_timer, jiffies + msecs_to_jiffies(500));
	}
	return 0;

fail_free_hdlc:
	buf_hdlc = NULL;
	driver->used = 0;
	diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
	mutex_unlock(&driver->diagchar_mutex);
	return ret;

fail_free_copy:
	diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
	return ret;
}
/*  Modem_request command */
static int lge_dm_tty_modem_request(const unsigned char *buf, int count)
{
	short modem_chip;
	int length;

#ifdef CONFIG_DIAG_HSIC_PIPE
	int err = 0;
#endif

	memcpy(&modem_chip, buf + dm_modem_request_header_length,
							sizeof(modem_chip));

	length = dm_modem_request_header_length + sizeof(modem_chip);

	if (modem_chip == Primary_modem_chip) {
		/* send masks to modem */
		diag_process_hdlc((void *)buf + length, count - length);
	} else if (modem_chip == Secondary_modem_chip) {

#ifdef CONFIG_DIAG_SDIO_PIPE
		/* send masks to 9k */
		if (driver->sdio_ch) {
			wait_event_interruptible(driver->wait_q,
				(sdio_write_avail(driver->sdio_ch)
					>= (count - length)));
			if (driver->sdio_ch && ((count - length) > 0)) {
				sdio_write(driver->sdio_ch,
					(void *)buf + length,
						count - length);
			}
		}
#endif

#ifdef CONFIG_DIAG_HSIC_PIPE
		/* send masks to 9k too */
		if (driver->hsic_ch && (count - length > 0)) {
			/* wait sending mask updates if HSIC ch not ready */
			if (driver->in_busy_hsic_write)
				wait_event_interruptible(driver->wait_q,
					(driver->in_busy_hsic_write != 1));
			driver->in_busy_hsic_write = 1;
			driver->in_busy_hsic_read_on_device = 0;
			err = diag_bridge_write((void *)buf + length,
							 count - length);
			if (err) {
				pr_err("diag: err sending mask to MDM: %d\n",
									 err);
				/*
				* If the error is recoverable, then clear
				* the write flag, so we will resubmit a
				* write on the next frame.  Otherwise, don't
				* resubmit a write on the next frame.
				*/
				if ((-ESHUTDOWN) != err)
					driver->in_busy_hsic_write = 0;
			}
		}
#endif

	} else {
		pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_write"
			"modem_number %d "
			"error count = %d length = %d\n",
			__func__, modem_chip, count, length);
	}

	return count;
}