int diag_md_copy_to_user(char __user *buf, int *pret)
{

	int i, j;
	int err = 0;
	int ret = *pret;
	int num_data = 0;
	int remote_token;
	unsigned long flags;
	struct diag_md_info *ch = NULL;
	struct diag_buf_tbl_t *entry = NULL;

	for (i = 0; i < NUM_DIAG_MD_DEV && !err; i++) {
		ch = &diag_md[i];
		for (j = 0; j < ch->num_tbl_entries && !err; j++) {
			entry = &ch->tbl[j];
			if (!entry || entry->len <= 0 || entry->buf == NULL)
				continue;
			/*
			 * If the data is from remote processor, copy the remote
			 * token first
			 */
			if (i > 0) {
				remote_token = diag_get_remote(i);
				err = copy_to_user(buf + ret, &remote_token,
						   sizeof(int));
				if (err)
					goto drop_data;
				ret += sizeof(int);
			}

			/* Copy the length of data being passed */
			err = copy_to_user(buf + ret, (void *)&(entry->len),
					   sizeof(int));
			if (err)
				goto drop_data;
			ret += sizeof(int);

			/* Copy the actual data being passed */
			err = copy_to_user(buf + ret, (void *)entry->buf,
					   entry->len);
			if (err)
				goto drop_data;
			ret += entry->len;

			/*
			 * The data is now copied to the user space client,
			 * Notify that the write is complete and delete its
			 * entry from the table
			 */
			num_data++;
drop_data:
			spin_lock_irqsave(&ch->lock, flags);
			if (ch->ops && ch->ops->write_done)
				ch->ops->write_done(entry->buf, entry->len,
						    entry->ctx, ch->ctx);
			diag_ws_on_copy(DIAG_WS_MD);
			entry->buf = NULL;
			entry->len = 0;
			entry->ctx = 0;
			spin_unlock_irqrestore(&ch->lock, flags);
		}
	}

	*pret = ret;
	err = copy_to_user(buf + sizeof(int), (void *)&num_data, sizeof(int));
	diag_ws_on_copy_complete(DIAG_WS_MD);
	return err;
}
int diag_md_copy_to_user(char __user *buf, int *pret, size_t buf_size,
			struct diag_md_session_t *info)
{
	int i, j;
	int err = 0;
	int ret = *pret;
	int num_data = 0;
	int remote_token;
	unsigned long flags;
	struct diag_md_info *ch = NULL;
	struct diag_buf_tbl_t *entry = NULL;
	uint8_t drain_again = 0;
	uint8_t peripheral = 0;
	struct diag_md_session_t *session_info = NULL;

	for (i = 0; i < NUM_DIAG_MD_DEV && !err; i++) {
		ch = &diag_md[i];
		for (j = 0; j < ch->num_tbl_entries && !err; j++) {
			entry = &ch->tbl[j];
			if (entry->len <= 0)
				continue;
			peripheral = GET_BUF_PERIPHERAL(entry->ctx);
			
			if (peripheral > NUM_PERIPHERALS)
				goto drop_data;
			session_info =
			diag_md_session_get_peripheral(peripheral);
			if (session_info && info &&
				(session_info->pid != info->pid))
				continue;
			if ((info && (info->peripheral_mask &
			    MD_PERIPHERAL_MASK(peripheral)) == 0))
				goto drop_data;
			if (i > 0) {
				if ((ret + (3 * sizeof(int)) + entry->len) >=
							buf_size) {
					drain_again = 1;
					break;
				}
			} else {
				if ((ret + (2 * sizeof(int)) + entry->len) >=
						buf_size) {
					drain_again = 1;
					break;
				}
			}
			if (i > 0) {
				remote_token = diag_get_remote(i);
				err = copy_to_user(buf + ret, &remote_token,
						   sizeof(int));
				if (err)
					goto drop_data;
				ret += sizeof(int);
			}

			
			err = copy_to_user(buf + ret, (void *)&(entry->len),
					   sizeof(int));
			if (err)
				goto drop_data;
			ret += sizeof(int);

			
			err = copy_to_user(buf + ret, (void *)entry->buf,
					   entry->len);
			if (err)
				goto drop_data;
			ret += entry->len;

			num_data++;
drop_data:
			spin_lock_irqsave(&ch->lock, flags);
			if (ch->ops && ch->ops->write_done)
				ch->ops->write_done(entry->buf, entry->len,
						    entry->ctx,
						    DIAG_MEMORY_DEVICE_MODE);
			diag_ws_on_copy(DIAG_WS_MUX);
			entry->buf = NULL;
			entry->len = 0;
			entry->ctx = 0;
			spin_unlock_irqrestore(&ch->lock, flags);
		}
	}

	*pret = ret;
	err = copy_to_user(buf + sizeof(int), (void *)&num_data, sizeof(int));
	diag_ws_on_copy_complete(DIAG_WS_MUX);
	if (drain_again)
		chk_logging_wakeup();

	return err;
}
Пример #3
0
static int lge_dm_tty_read_thread(void *data)
{
	int i = 0;
	struct dm_tty *lge_dm_tty_drv = NULL;
	int copy_data = 0;
    unsigned long flags;

	lge_dm_tty_drv = lge_dm_tty;

	while (1) {

		wait_event_interruptible(lge_dm_tty->waitq,
			lge_dm_tty->set_logging);

		mutex_lock(&driver->diagchar_mutex);

		if ((lge_dm_tty->set_logging == 1)
				&& (driver->logging_mode == DM_APP_MODE)) {

			/* copy modem data */	
			for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
				struct diag_smd_info *data = &driver->smd_data[i];

				if (data->in_busy_1 == 1) {
					lge_dm_tty_modem_response(
					lge_dm_tty_drv,
					data->buf_in_1,
					data->write_ptr_1->length);

					diag_ws_on_copy();
					copy_data = 1;

                    spin_lock_irqsave(&data->in_busy_lock, flags);
					data->in_busy_1 = 0;
                    spin_unlock_irqrestore(&data->in_busy_lock, flags);
				}

				if (data->in_busy_2 == 1) {
					lge_dm_tty_modem_response(
					lge_dm_tty_drv,
					data->buf_in_2,
					data->write_ptr_2->length);

					diag_ws_on_copy();
					copy_data = 1;

                    spin_lock_irqsave(&data->in_busy_lock, flags);
					data->in_busy_2 = 0;
                    spin_unlock_irqrestore(&data->in_busy_lock, flags);
				}
			}

			if(lge_dm_tty_drv->logging_mode == DM_APP_SDM)
			{
				for (i = 0; i < NUM_SMD_CMD_CHANNELS; i++) {
					struct diag_smd_info *cmd = &driver->smd_cmd[i];
						if (cmd->in_busy_1 == 1) {
							if(cmd->write_ptr_1->length > 0 && cmd->buf_in_1 != NULL){
								lge_dm_tty_modem_response(
								lge_dm_tty_drv,
								cmd->buf_in_1,
								cmd->write_ptr_1->length);
							}

							cmd->in_busy_1 = 0;
						}

				}
			}

			lge_dm_tty->set_logging = 0;

			for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
				if (driver->smd_data[i].ch)
					queue_work(driver->diag_wq,
					&(driver->smd_data[i].diag_read_smd_work));
			}

		}

		mutex_unlock(&driver->diagchar_mutex);
		if (copy_data) {
			/*
			 * Flush any work that is currently pending on the data
			 * channels. This will ensure that the next read is not
			 * missed.
			 */
			for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++)
				flush_workqueue(driver->smd_data[i].wq);
			wake_up(&driver->smd_wait_q);
			diag_ws_on_copy_complete();
		}

		if (kthread_should_stop())
			break;
		mdelay(1);

	}

	return 0;

}
static int lge_dm_tty_read_thread(void *data)
{
    int j = 0;
    struct dm_tty *lge_dm_tty_drv = NULL;
    struct diag_buf_tbl_t *entry = NULL;
    unsigned long flags;

    int i = 0;

    lge_dm_tty_drv = lge_dm_tty;

    while (1) {

        wait_event_interruptible(lge_dm_tty->waitq,
            lge_dm_tty->set_logging);

        mutex_lock(&driver->diagchar_mutex);

        if ((lge_dm_tty->set_logging == 1)
                && (driver->logging_mode == DM_APP_MODE)) {

            lge_dm_tty->set_logging = 0;

            for (j = 0; j < lge_dm_tty->num_tbl_entries; j++) {
                entry = &lge_dm_tty->tbl[j];
                if ((entry->len <= 0) || ((void *)entry->buf == NULL))
                    continue;

                lge_dm_tty_modem_response(
                    lge_dm_tty_drv,
                    Primary_modem_chip,
                    (void *)entry->buf,
                    entry->len);

                lge_dm_tty->ops->write_done(entry->buf, entry->len,
                            entry->ctx, lge_dm_tty->ctx);
                diag_ws_on_copy(DIAG_WS_MD);
                spin_lock_irqsave(&entry->lock, flags);
                entry->buf = NULL;
                entry->len = 0;
                entry->ctx = 0;
                spin_unlock_irqrestore(&entry->lock, flags);
            }

           for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
                /* Poll SMD data channels to check for data */
                queue_work(driver->smd_data[i].wq,
                    &(driver->smd_data[i].diag_read_smd_work));
            }

            for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++)
                flush_workqueue(driver->smd_data[i].wq);
            wake_up(&driver->smd_wait_q);

            diag_ws_on_copy_complete(DIAG_WS_MD);

        }

        mutex_unlock(&driver->diagchar_mutex);

        if (kthread_should_stop())
            break;
        mdelay(1);

    }

    return 0;

}