static int hsic_write(int id, unsigned char *buf, int len, int ctxt)
{
	int err = 0;
	struct diag_hsic_info *ch = NULL;

	if (id < 0 || id >= NUM_HSIC_DEV) {
		pr_err_ratelimited("diag: In %s, invalid index %d\n",
				   __func__, id);
		return -EINVAL;
	}
	if (!buf || len <= 0) {
		pr_err_ratelimited("diag: In %s, ch %d, invalid buf %pK len %d\n",
				   __func__, id, buf, len);
		return -EINVAL;
	}

	ch = &diag_hsic[id];
	if (!ch->opened || !ch->enabled) {
		pr_debug_ratelimited("diag: In %s, ch %d is disabled. opened %d enabled: %d\n",
				     __func__, id, ch->opened, ch->enabled);
		return -EIO;
	}

	err = diag_bridge_write(ch->id, buf, len);
	if (err) {
		pr_err_ratelimited("diag: cannot write to HSIC ch %d, err: %d\n",
				   ch->id, err);
	}
	return err;
}
Beispiel #2
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++;
    }
}
Beispiel #3
0
/* Called after the asychronous usb_diag_read() on mdm channel is complete */
static int diagfwd_read_complete_bridge(struct diag_request *diag_read_ptr)
{
	/* The read of the usb driver on the mdm (not hsic) has completed */
	driver->in_busy_hsic_read_on_device = 0;
	driver->read_len_mdm = diag_read_ptr->actual;

	if (driver->diag_smux_enabled) {
		diagfwd_read_complete_smux();
		return 0;
	}
	/* If SMUX not enabled, check for HSIC */
	if (!driver->hsic_ch) {
		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
		return 0;
	}

	/*
	 * The read of the usb driver on the mdm channel has completed.
	 * If there is no write on the hsic in progress, check if the
	 * read has data to pass on to the hsic. If so, pass the usb
	 * mdm data on to the hsic.
	 */
	if (!driver->in_busy_hsic_write && driver->usb_buf_mdm_out &&
		(driver->read_len_mdm > 0)) {

		/*
		 * Initiate the hsic write. The hsic write is
		 * asynchronous. When complete the write
		 * complete callback function will be called
		 */
		int err;
		driver->in_busy_hsic_write = 1;
		err = diag_bridge_write(driver->usb_buf_mdm_out,
					driver->read_len_mdm);
		if (err) {
			pr_err_ratelimited("DIAG: mdm data on hsic write err: %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 ((-ENODEV) != err)
				driver->in_busy_hsic_write = 0;
		}
	}

	/*
	 * If there is no write of the usb mdm data on the
	 * hsic channel
	 */
	if (!driver->in_busy_hsic_write)
		queue_work(driver->diag_bridge_wq, &driver->diag_read_mdm_work);

	return 0;
}
/* Work function used to send zero cfg packet and receive ack */
static void diag_zero_cfg_hsic_work_fn(struct work_struct *work)
{
	int index = driver->zero_cfg_packet_lens_index;
	if (index >= ZERO_CFG_SUBPACKET_MAX)
		return;

	if (!driver->in_busy_hsic_write && !driver->in_busy_hsic_read) {
		driver->in_busy_hsic_write = 1;
		diag_bridge_write(&zero_cfg_buf[driver->zero_cfg_index],
						zero_cfg_packet_lens[index]);
		driver->in_busy_hsic_read = 1;
		diag_bridge_read((char *)driver->buf_in_hsic,
				IN_BUF_SIZE);
	}
}
/*  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;
}
/* Called after the asychronous usb_diag_read() on mdm channel is complete */
int diagfwd_read_complete_bridge(struct diag_request *diag_read_ptr)
{
	 int index = (int)(diag_read_ptr->context);

	/* The read of the usb on the mdm (not HSIC/SMUX) has completed */
	diag_bridge[index].read_len = diag_read_ptr->actual;

	if (index == SMUX) {
		if (driver->diag_smux_enabled) {
			diagfwd_read_complete_smux();
			return 0;
		} else {
			pr_warning("diag: incorrect callback for smux\n");
		}
	}

	/* If SMUX not enabled, check for HSIC */
	diag_hsic[index].in_busy_hsic_read_on_device = 0;
	if (!diag_hsic[index].hsic_ch) {
		pr_err("DIAG in %s: hsic_ch == 0, ch %d\n", __func__, index);
		return 0;
	}

	/*
	 * The read of the usb driver on the mdm channel has completed.
	 * If there is no write on the HSIC in progress, check if the
	 * read has data to pass on to the HSIC. If so, pass the usb
	 * mdm data on to the HSIC.
	 */
	if (!diag_hsic[index].in_busy_hsic_write &&
		diag_bridge[index].usb_buf_out &&
		(diag_bridge[index].read_len > 0)) {

		/*
		 * Initiate the HSIC write. The HSIC write is
		 * asynchronous. When complete the write
		 * complete callback function will be called
		 */
		int err;
		diag_hsic[index].in_busy_hsic_write = 1;
		err = diag_bridge_write(index, diag_bridge[index].usb_buf_out,
					diag_bridge[index].read_len);
		if (err) {
			pr_err_ratelimited("diag: mdm data on HSIC write err: %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 ((-ENODEV) != err)
				diag_hsic[index].in_busy_hsic_write = 0;
		}
	}

	/*
	 * If there is no write of the usb mdm data on the
	 * HSIC channel
	 */
	if (!diag_hsic[index].in_busy_hsic_write)
		queue_work(diag_bridge[index].wq,
			 &diag_bridge[index].diag_read_work);

	return 0;
}
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 == 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;
}
static int diagfwd_read_complete_bridge(struct diag_request *diag_read_ptr)
{
	
	driver->in_busy_hsic_read_on_device = 0;
	driver->read_len_mdm = diag_read_ptr->actual;

	if (driver->diag_smux_enabled) {
		diagfwd_read_complete_smux();
		return 0;
	}
	
	if (!driver->hsic_ch) {
		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
		return 0;
	}

#if DIAG_XPST && defined(CONFIG_DIAG_BRIDGE_CODE)
	if (!driver->in_busy_hsic_write && driver->usb_buf_mdm_out &&
		(driver->read_len_mdm > 0) && !driver->nohdlc) {
#else
	if (!driver->in_busy_hsic_write && driver->usb_buf_mdm_out &&
		(driver->read_len_mdm > 0)) {
#endif

		int err;
		driver->in_busy_hsic_write = 1;
		err = diag_bridge_write(driver->usb_buf_mdm_out,
					driver->read_len_mdm);
		if (err) {
			pr_err_ratelimited("diag: mdm data on hsic write err: %d\n",
					err);
			if ((-ENODEV) != err)
				driver->in_busy_hsic_write = 0;
		}
	}

	if (!driver->in_busy_hsic_write)
		queue_work(driver->diag_bridge_wq, &driver->diag_read_mdm_work);

	return 0;
}

static void diagfwd_bridge_notifier(void *priv, unsigned event,
					struct diag_request *d_req)
{
	switch (event) {
	case USB_DIAG_CONNECT:
		diagfwd_connect_bridge(1);
		break;
	case USB_DIAG_DISCONNECT:
		queue_work(driver->diag_bridge_wq,
			 &driver->diag_disconnect_work);
		break;
	case USB_DIAG_READ_DONE:
		queue_work(driver->diag_bridge_wq,
				&driver->diag_usb_read_complete_work);
		break;
	case USB_DIAG_WRITE_DONE:
		if (driver->hsic_device_enabled)
			diagfwd_write_complete_hsic(d_req);
		else if (driver->diag_smux_enabled)
			diagfwd_write_complete_smux();
		break;
	default:
		pr_err("diag: in %s: Unknown event from USB diag:%u\n",
			__func__, event);
		break;
	}
}

static void diag_usb_read_complete_fn(struct work_struct *w)
{
	diagfwd_read_complete_bridge(driver->usb_read_mdm_ptr);
}
int diagfwd_read_complete_bridge(struct diag_request *diag_read_ptr)
{
	 int index = (int)(diag_read_ptr->context);

	
	diag_bridge[index].read_len = diag_read_ptr->actual;

	if (index == SMUX) {
		if (driver->diag_smux_enabled) {
			diagfwd_read_complete_smux();
			return 0;
		} else {
			pr_warning("diag: incorrect callback for smux\n");
		}
	}

	
	driver->in_busy_hsic_read_on_device = 0;
	if (!driver->hsic_ch) {
		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
		return 0;
	}

#if DIAG_XPST
	if (!driver->in_busy_hsic_write && diag_bridge[HSIC].usb_buf_out &&
		(diag_bridge[HSIC].read_len > 0) && !driver->nohdlc) {
#else
	if (!driver->in_busy_hsic_write && diag_bridge[HSIC].usb_buf_out &&
		(diag_bridge[HSIC].read_len > 0)) {
#endif

		int err;
		driver->in_busy_hsic_write = 1;
		err = diag_bridge_write(diag_bridge[HSIC].usb_buf_out,
					diag_bridge[HSIC].read_len);
		if (err) {
			pr_err_ratelimited("diag: mdm data on HSIC write err: %d\n",
					err);
			if ((-ENODEV) != err)
				driver->in_busy_hsic_write = 0;
		}
	}

	if (!driver->in_busy_hsic_write)
		queue_work(diag_bridge[HSIC].wq,
			 &diag_bridge[HSIC].diag_read_work);

	return 0;
}

static void diagfwd_bridge_notifier(void *priv, unsigned event,
					struct diag_request *d_req)
{
	int index;

	switch (event) {
	case USB_DIAG_CONNECT:
		diagfwd_connect_bridge(1);
		break;
	case USB_DIAG_DISCONNECT:
		queue_work(driver->diag_wq,
			 &driver->diag_disconnect_work);
		break;
	case USB_DIAG_READ_DONE:
		index = (int)(d_req->context);
		queue_work(diag_bridge[index].wq,
		&diag_bridge[index].usb_read_complete_work);
		break;
	case USB_DIAG_WRITE_DONE:
		index = (int)(d_req->context);
		if (index == HSIC &&  driver->hsic_device_enabled)
			diagfwd_write_complete_hsic(d_req);
		else if (index == SMUX && driver->diag_smux_enabled)
			diagfwd_write_complete_smux();
		break;
	default:
		pr_err("diag: in %s: Unknown event from USB diag:%u\n",
			__func__, event);
		break;
	}
}
/*  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;
}
/* Called after the asychronous usb_diag_read() on mdm channel is complete */
int diagfwd_read_complete_bridge(struct diag_request *diag_read_ptr)
{
	 int index = (int)(diag_read_ptr->context);

	/* The read of the usb on the mdm (not HSIC/SMUX) has completed */
	diag_bridge[index].read_len = diag_read_ptr->actual;

	if (index == SMUX) {
		if (driver->diag_smux_enabled) {
			diagfwd_read_complete_smux();
			return 0;
		} else {
			pr_warning("diag: incorrect callback for smux\n");
		}
	}

	/* If SMUX not enabled, check for HSIC */
	diag_hsic[index].in_busy_hsic_read_on_device = 0;
	if (!diag_hsic[index].hsic_ch) {
		pr_err("DIAG in %s: hsic_ch == 0, ch %d\n", __func__, index);
		return 0;
	}

	/*
	 * The read of the usb driver on the mdm channel has completed.
	 * If there is no write on the HSIC in progress, check if the
	 * read has data to pass on to the HSIC. If so, pass the usb
	 * mdm data on to the HSIC.
	 */
#if DIAG_XPST
	if (!diag_hsic[index].in_busy_hsic_write &&
		diag_bridge[index].usb_buf_out &&
		(diag_bridge[index].read_len > 0) && !driver->nohdlc) {
#else
	if (!diag_hsic[index].in_busy_hsic_write &&
		diag_bridge[index].usb_buf_out &&
		(diag_bridge[index].read_len > 0)) {
#endif
		/*
		 * Initiate the HSIC write. The HSIC write is
		 * asynchronous. When complete the write
		 * complete callback function will be called
		 */
		int err;
		diag_hsic[index].in_busy_hsic_write = 1;
		err = diag_bridge_write(index, diag_bridge[index].usb_buf_out,
					diag_bridge[index].read_len);
		if (err) {
			pr_err_ratelimited("diag: mdm data on HSIC write err: %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 ((-ENODEV) != err)
				diag_hsic[index].in_busy_hsic_write = 0;
		}
	}

	/*
	 * If there is no write of the usb mdm data on the
	 * HSIC channel
	 */
	if (!diag_hsic[index].in_busy_hsic_write)
		queue_work(diag_bridge[index].wq,
			 &diag_bridge[index].diag_read_work);

	return 0;
}

static void diagfwd_bridge_notifier(void *priv, unsigned event,
					struct diag_request *d_req)
{
	int index;

	switch (event) {
	case USB_DIAG_CONNECT:
		queue_work(driver->diag_wq,
			 &driver->diag_connect_work);
		break;
	case USB_DIAG_DISCONNECT:
		queue_work(driver->diag_wq,
			 &driver->diag_disconnect_work);
		break;
	case USB_DIAG_READ_DONE:
		index = (int)(d_req->context);
		queue_work(diag_bridge[index].wq,
		&diag_bridge[index].usb_read_complete_work);
		break;
	case USB_DIAG_WRITE_DONE:
		index = (int)(d_req->context);
		if (index == SMUX && driver->diag_smux_enabled)
			diagfwd_write_complete_smux();
		else if (diag_hsic[index].hsic_device_enabled)
			diagfwd_write_complete_hsic(d_req, index);
		break;
	default:
		pr_err("diag: in %s: Unknown event from USB diag:%u\n",
			__func__, event);
		break;
	}
}
/* modem_request_command */
static int lge_dm_dev_tty_modem_request(const unsigned char *buf, int count)
{
#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
	int err = 0;
#endif /*CONFIG_DIAGFWD_BRIDGE_CODE*/

	int index = 0;
//	unsigned int payload_size;
//	int remote_proc = 0;
	//int token_offset = 0;


	
#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));
	if (driver->sdio_ch && (count > 0)) {
	  sdio_write(driver->sdio_ch,
	      (void *)buf, count);
		}
	}
#endif /*CONFIG_DIAG_SDIO_PIPE*/

#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, 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;
}