コード例 #1
0
static int diagchar_read(struct file *file, char __user *buf, size_t count,
			  loff_t *ppos)
{
	int index = -1, i = 0, ret = 0;
	int num_data = 0, data_type;
	for (i = 0; i < driver->num_clients; i++)
		if (driver->client_map[i].pid == current->tgid)
			index = i;

	if (index == -1) {
		pr_err("diag: Client PID not found in table");
		return -EINVAL;
	}

	wait_event_interruptible(driver->wait_q,
				  driver->data_ready[index]);
	mutex_lock(&driver->diagchar_mutex);

	if ((driver->data_ready[index] & USER_SPACE_LOG_TYPE) && (driver->
					logging_mode == MEMORY_DEVICE_MODE)) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & USER_SPACE_LOG_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		/* place holder for number of data field */
		ret += 4;

		for (i = 0; i < driver->poolsize_write_struct; i++) {
			if (driver->buf_tbl[i].length > 0) {
#ifdef DIAG_DEBUG
				pr_debug("diag: WRITING the buf address "
				       "and length is %x , %d\n", (unsigned int)
					(driver->buf_tbl[i].buf),
					driver->buf_tbl[i].length);
#endif
				num_data++;
				/* Copy the length of data being passed */
				if (copy_to_user(buf+ret, (void *)&(driver->
						buf_tbl[i].length), 4)) {
						num_data--;
						goto drop;
				}
				ret += 4;

				/* Copy the actual data being passed */
				if (copy_to_user(buf+ret, (void *)driver->
				buf_tbl[i].buf, driver->buf_tbl[i].length)) {
					ret -= 4;
					num_data--;
					goto drop;
				}
				ret += driver->buf_tbl[i].length;
drop:
#ifdef DIAG_DEBUG
				pr_debug("diag: DEQUEUE buf address and"
				       " length is %x,%d\n", (unsigned int)
				       (driver->buf_tbl[i].buf), driver->
				       buf_tbl[i].length);
#endif
				diagmem_free(driver, (unsigned char *)
				(driver->buf_tbl[i].buf), POOL_TYPE_HDLC);
				driver->buf_tbl[i].length = 0;
				driver->buf_tbl[i].buf = 0;
			}
		}

		/* copy modem data */
		if (driver->in_busy_1 == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					 (driver->write_ptr_1->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					*(driver->buf_in_1),
					 driver->write_ptr_1->length);
			driver->in_busy_1 = 0;
		}
		if (driver->in_busy_2 == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					 (driver->write_ptr_2->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					 *(driver->buf_in_2),
					 driver->write_ptr_2->length);
			driver->in_busy_2 = 0;
		}
		/* copy lpass data */
		if (driver->in_busy_qdsp_1 == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
				 (driver->write_ptr_qdsp_1->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
							buf_in_qdsp_1),
					 driver->write_ptr_qdsp_1->length);
			driver->in_busy_qdsp_1 = 0;
		}
		if (driver->in_busy_qdsp_2 == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
				 (driver->write_ptr_qdsp_2->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
				buf_in_qdsp_2), driver->
					write_ptr_qdsp_2->length);
			driver->in_busy_qdsp_2 = 0;
		}
		/* copy wncss data */
		if (driver->in_busy_wcnss == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
				 (driver->write_ptr_wcnss->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
							buf_in_wcnss),
					 driver->write_ptr_wcnss->length);
			driver->in_busy_wcnss = 0;
		}
#ifdef CONFIG_DIAG_SDIO_PIPE
		/* copy 9K data over SDIO */
		if (driver->in_busy_sdio == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
				 (driver->write_ptr_mdm->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					*(driver->buf_in_sdio),
					 driver->write_ptr_mdm->length);
			driver->in_busy_sdio = 0;
		}
#endif
		/* copy number of data fields */
		COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4);
		ret -= 4;
		driver->data_ready[index] ^= USER_SPACE_LOG_TYPE;
		if (driver->ch)
			queue_work(driver->diag_wq,
					 &(driver->diag_read_smd_work));
		if (driver->chqdsp)
			queue_work(driver->diag_wq,
					 &(driver->diag_read_smd_qdsp_work));
		if (driver->ch_wcnss)
			queue_work(driver->diag_wq,
					 &(driver->diag_read_smd_wcnss_work));
#ifdef CONFIG_DIAG_SDIO_PIPE
		if (driver->sdio_ch)
			queue_work(driver->diag_sdio_wq,
					   &(driver->diag_read_sdio_work));
#endif
		APPEND_DEBUG('n');
		goto exit;
	} else if (driver->data_ready[index] & USER_SPACE_LOG_TYPE) {
		/* In case, the thread wakes up and the logging mode is
		not memory device any more, the condition needs to be cleared */
		driver->data_ready[index] ^= USER_SPACE_LOG_TYPE;
	}

	if (driver->data_ready[index] & DEINIT_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & DEINIT_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		driver->data_ready[index] ^= DEINIT_TYPE;
		goto exit;
	}

	if (driver->data_ready[index] & MSG_MASKS_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & MSG_MASKS_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->msg_masks),
							 MSG_MASK_SIZE);
		driver->data_ready[index] ^= MSG_MASKS_TYPE;
		goto exit;
	}

	if (driver->data_ready[index] & EVENT_MASKS_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & EVENT_MASKS_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->event_masks),
							 EVENT_MASK_SIZE);
		driver->data_ready[index] ^= EVENT_MASKS_TYPE;
		goto exit;
	}

	if (driver->data_ready[index] & LOG_MASKS_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & LOG_MASKS_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->log_masks),
							 LOG_MASK_SIZE);
		driver->data_ready[index] ^= LOG_MASKS_TYPE;
		goto exit;
	}

	if (driver->data_ready[index] & PKT_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & PKT_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->pkt_buf),
							 driver->pkt_length);
		driver->data_ready[index] ^= PKT_TYPE;
		goto exit;
	}

exit:
	mutex_unlock(&driver->diagchar_mutex);
	return ret;
}
コード例 #2
0
static int diagchar_read(struct file *file, char __user *buf, size_t count,
			  loff_t *ppos)
{
	int index = -1, i = 0, ret = 0;
	int num_data = 0, data_type;

#ifdef SDQXDM_DEBUG
	struct timeval t;
#endif

/*
	printk(KERN_INFO "%s:%s(parent:%s): tgid=%d\n", __func__,
	current->comm, current->parent->comm, current->tgid);
*/
	for (i = 0; i < driver->num_clients; i++)
		if (driver->client_map[i].pid == current->tgid)
			index = i;

	if (index == -1) {
		DIAG_ERR("\n Client PID not found in table");
		return -EINVAL;
	}

	wait_event_interruptible(driver->wait_q,
				  driver->data_ready[index]);
	mutex_lock(&driver->diagchar_mutex);

	if ((driver->data_ready[index] & MEMORY_DEVICE_LOG_TYPE) && (driver->
					logging_mode == MEMORY_DEVICE_MODE)) {

		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & MEMORY_DEVICE_LOG_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		/* place holder for number of data field */
		ret += 4;

		for (i = 0; i < driver->poolsize_write_struct; i++) {
			if (driver->buf_tbl[i].length > 0) {
#ifdef DIAG_DEBUG
				printk(KERN_INFO "\n WRITING the buf address "
				       "and length is %x , %d\n", (unsigned int)
					(driver->buf_tbl[i].buf),
					driver->buf_tbl[i].length);
#endif
				num_data++;
				/* Copy the length of data being passed */
				if (copy_to_user(buf+ret, (void *)&(driver->
						buf_tbl[i].length), 4)) {
						num_data--;
						goto drop;
				}
				ret += 4;

				/* Copy the actual data being passed */
				if (copy_to_user(buf+ret, (void *)driver->
				buf_tbl[i].buf, driver->buf_tbl[i].length)) {
					ret -= 4;
					num_data--;
					goto drop;
				}
				ret += driver->buf_tbl[i].length;
drop:
#ifdef DIAG_DEBUG
				printk(KERN_INFO "\n DEQUEUE buf address and"
				       " length is %x,%d\n", (unsigned int)
				       (driver->buf_tbl[i].buf), driver->
				       buf_tbl[i].length);
#endif
				diagmem_free(driver, (unsigned char *)
				(driver->buf_tbl[i].buf), POOL_TYPE_HDLC);
				driver->buf_tbl[i].length = 0;
				driver->buf_tbl[i].buf = 0;
			}
		}

		/* copy modem data */
		if (driver->in_busy_1 == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					 (driver->write_ptr_1->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					*(driver->buf_in_1),
					 driver->write_ptr_1->length);
			driver->in_busy_1 = 0;
		}
		if (driver->in_busy_2 == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					 (driver->write_ptr_2->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					 *(driver->buf_in_2),
					 driver->write_ptr_2->length);
			driver->in_busy_2 = 0;
		}

		/* copy q6 data */
		if (driver->in_busy_qdsp_1 == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
				 (driver->write_ptr_qdsp_1->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
							buf_in_qdsp_1),
					 driver->write_ptr_qdsp_1->length);
			driver->in_busy_qdsp_1 = 0;
		}
		if (driver->in_busy_qdsp_2 == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
				 (driver->write_ptr_qdsp_2->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
				buf_in_qdsp_2), driver->
					write_ptr_qdsp_2->length);
			driver->in_busy_qdsp_2 = 0;
		}
#if 0 /* def CONFIG_ARCH_MSM8X60_LTE */
		if (driver->in_busy_sdio == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
				 (driver->write_ptr_mdm->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
				buf_in_sdio), driver->
					write_ptr_mdm->length);
			driver->in_busy_sdio = 0;
		}
#endif
		/* copy number of data fields */
		COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4);
		ret -= 4;

		driver->data_ready[index] ^= MEMORY_DEVICE_LOG_TYPE;
#if 0 /* def CONFIG_ARCH_MSM8X60_LTE */
		if (mdm_diag) {
			if (driver->sdio_ch)
				queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work));
		}
#endif
		if (driver->ch)
			queue_work(driver->diag_wq,
					 &(driver->diag_read_smd_work));
		if (driver->chqdsp)
			queue_work(driver->diag_wq,
					 &(driver->diag_read_smd_qdsp_work));
		APPEND_DEBUG('n');
		goto exit;
	} else if (driver->data_ready[index] & MEMORY_DEVICE_LOG_TYPE) {
		/* In case, the thread wakes up and the logging mode is
		not memory device any more, the condition needs to be cleared */
		driver->data_ready[index] ^= MEMORY_DEVICE_LOG_TYPE;
	} else if (driver->data_ready[index] & USERMODE_DIAGFWD) {
		data_type = USERMODE_DIAGFWD;
		driver->data_ready[index] ^= USERMODE_DIAGFWD;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);

#ifdef SDQXDM_DEBUG
		do_gettimeofday(&t);

		if (driver->in_busy_1 && t.tv_sec > driver->write_ptr_1->second + 2)
			pr_info("[diag-dbg] late pkt now: %ld.%04ld pkt: %d\n", t.tv_sec, t.tv_usec/1000, driver->write_ptr_1->second);
		if (driver->in_busy_2 && t.tv_sec > driver->write_ptr_2->second + 2)
			pr_info("[diag-dbg] late pkt now: %ld.%04ld pkt: %d\n", t.tv_sec, t.tv_usec/1000, driver->write_ptr_2->second);
#endif
		/* copy modem data */
		if (driver->in_busy_1 == 1) {
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					*(driver->buf_in_1),
					 driver->write_ptr_1->length);
			driver->in_busy_1 = 0;
		}
		if (driver->in_busy_2 == 1) {
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					 *(driver->buf_in_2),
					 driver->write_ptr_2->length);
			driver->in_busy_2 = 0;
		}

		/* copy q6 data */
		if (driver->in_busy_qdsp_1 == 1) {
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
							buf_in_qdsp_1),
					 driver->write_ptr_qdsp_1->length);
			driver->in_busy_qdsp_1 = 0;
		}
		if (driver->in_busy_qdsp_2 == 1) {
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
				buf_in_qdsp_2), driver->
					write_ptr_qdsp_2->length);
			driver->in_busy_qdsp_2 = 0;
		}
#if 0 /* def CONFIG_ARCH_MSM8X60_LTE */
		if (driver->in_busy_sdio == 1) {
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
				buf_in_sdio), driver->
					write_ptr_mdm->length);
			driver->in_busy_sdio = 0;
		}
		if (mdm_diag) {
			if (driver->sdio_ch)
				queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work));
		}
#endif
		if (driver->ch)
			queue_work(driver->diag_wq,
					 &(driver->diag_read_smd_work));
		if (driver->chqdsp)
			queue_work(driver->diag_wq,
					 &(driver->diag_read_smd_qdsp_work));
#ifdef DIAG_DEBUG
		pr_info("%s() return %d byte\n", __func__, ret);
#endif

		goto exit;
	}

	if (driver->data_ready[index] & DEINIT_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & DEINIT_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		driver->data_ready[index] ^= DEINIT_TYPE;
		goto exit;
	}

	if (driver->data_ready[index] & MSG_MASKS_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & MSG_MASKS_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->msg_masks),
							 MSG_MASK_SIZE);
		driver->data_ready[index] ^= MSG_MASKS_TYPE;
		goto exit;
	}

	if (driver->data_ready[index] & EVENT_MASKS_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & EVENT_MASKS_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->event_masks),
							 EVENT_MASK_SIZE);
		driver->data_ready[index] ^= EVENT_MASKS_TYPE;
		goto exit;
	}

	if (driver->data_ready[index] & LOG_MASKS_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & LOG_MASKS_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->log_masks),
							 LOG_MASK_SIZE);
		driver->data_ready[index] ^= LOG_MASKS_TYPE;
		goto exit;
	}

	if (driver->data_ready[index] & PKT_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & PKT_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->pkt_buf),
							 driver->pkt_length);
		driver->data_ready[index] ^= PKT_TYPE;
		goto exit;
	}

exit:
	if (ret)
		wake_lock_timeout(&driver->wake_lock, HZ / 2);

	mutex_unlock(&driver->diagchar_mutex);
	return ret;
}
コード例 #3
0
ファイル: diagchar_core.c プロジェクト: nsingh94/msm7x30-caf
static int diagchar_read(struct file *file, char __user *buf, size_t count,
                         loff_t *ppos)
{
    int index = -1, i = 0, ret = 0;
    int num_data = 0, data_type;
    for (i = 0; i < driver->num_clients; i++)
        if (driver->client_map[i].pid == current->tgid)
            index = i;

    if (index == -1) {
        pr_err("diag: Client PID not found in table");
        return -EINVAL;
    }

    wait_event_interruptible(driver->wait_q,
                             driver->data_ready[index]);
    mutex_lock(&driver->diagchar_mutex);

    if ((driver->data_ready[index] & USER_SPACE_LOG_TYPE) && (driver->
            logging_mode == MEMORY_DEVICE_MODE)) {
#ifdef CONFIG_DIAG_BRIDGE_CODE
        unsigned long spin_lock_flags;
        struct diag_write_device hsic_buf_tbl[NUM_HSIC_BUF_TBL_ENTRIES];
#endif

        pr_debug("diag: process woken up\n");
        /*Copy the type of data being passed*/
        data_type = driver->data_ready[index] & USER_SPACE_LOG_TYPE;
        COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
        /* place holder for number of data field */
        ret += 4;

        for (i = 0; i < driver->poolsize_write_struct; i++) {
            if (driver->buf_tbl[i].length > 0) {
#ifdef DIAG_DEBUG
                pr_debug("diag: WRITING the buf address "
                         "and length is %x , %d\n", (unsigned int)
                         (driver->buf_tbl[i].buf),
                         driver->buf_tbl[i].length);
#endif
                num_data++;
                /* Copy the length of data being passed */
                if (copy_to_user(buf+ret, (void *)&(driver->
                                                    buf_tbl[i].length), 4)) {
                    num_data--;
                    goto drop;
                }
                ret += 4;

                /* Copy the actual data being passed */
                if (copy_to_user(buf+ret, (void *)driver->
                                 buf_tbl[i].buf, driver->buf_tbl[i].length)) {
                    ret -= 4;
                    num_data--;
                    goto drop;
                }
                ret += driver->buf_tbl[i].length;
drop:
#ifdef DIAG_DEBUG
                pr_debug("diag: DEQUEUE buf address and"
                         " length is %x,%d\n", (unsigned int)
                         (driver->buf_tbl[i].buf), driver->
                         buf_tbl[i].length);
#endif
                diagmem_free(driver, (unsigned char *)
                             (driver->buf_tbl[i].buf), POOL_TYPE_HDLC);
                driver->buf_tbl[i].length = 0;
                driver->buf_tbl[i].buf = 0;
            }
        }

        /* copy modem data */
        if (driver->in_busy_1 == 1) {
            num_data++;
            /*Copy the length of data being passed*/
            COPY_USER_SPACE_OR_EXIT(buf+ret,
                                    (driver->write_ptr_1->length), 4);
            /*Copy the actual data being passed*/
            COPY_USER_SPACE_OR_EXIT(buf+ret,
                                    *(driver->buf_in_1),
                                    driver->write_ptr_1->length);
            driver->in_busy_1 = 0;
        }
        if (driver->in_busy_2 == 1) {
            num_data++;
            /*Copy the length of data being passed*/
            COPY_USER_SPACE_OR_EXIT(buf+ret,
                                    (driver->write_ptr_2->length), 4);
            /*Copy the actual data being passed*/
            COPY_USER_SPACE_OR_EXIT(buf+ret,
                                    *(driver->buf_in_2),
                                    driver->write_ptr_2->length);
            driver->in_busy_2 = 0;
        }
        /* copy lpass data */
        if (driver->in_busy_qdsp_1 == 1) {
            num_data++;
            /*Copy the length of data being passed*/
            COPY_USER_SPACE_OR_EXIT(buf+ret,
                                    (driver->write_ptr_qdsp_1->length), 4);
            /*Copy the actual data being passed*/
            COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
                                               buf_in_qdsp_1),
                                    driver->write_ptr_qdsp_1->length);
            driver->in_busy_qdsp_1 = 0;
        }
        if (driver->in_busy_qdsp_2 == 1) {
            num_data++;
            /*Copy the length of data being passed*/
            COPY_USER_SPACE_OR_EXIT(buf+ret,
                                    (driver->write_ptr_qdsp_2->length), 4);
            /*Copy the actual data being passed*/
            COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
                                               buf_in_qdsp_2), driver->
                                    write_ptr_qdsp_2->length);
            driver->in_busy_qdsp_2 = 0;
        }
        /* copy wncss data */
        if (driver->in_busy_wcnss_1 == 1) {
            num_data++;
            /*Copy the length of data being passed*/
            COPY_USER_SPACE_OR_EXIT(buf+ret,
                                    (driver->write_ptr_wcnss_1->length), 4);
            /*Copy the actual data being passed*/
            COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
                                               buf_in_wcnss_1),
                                    driver->write_ptr_wcnss_1->length);
            driver->in_busy_wcnss_1 = 0;
        }
        if (driver->in_busy_wcnss_2 == 1) {
            num_data++;
            /*Copy the length of data being passed*/
            COPY_USER_SPACE_OR_EXIT(buf+ret,
                                    (driver->write_ptr_wcnss_2->length), 4);
            /*Copy the actual data being passed*/
            COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
                                               buf_in_wcnss_2),
                                    driver->write_ptr_wcnss_2->length);
            driver->in_busy_wcnss_2 = 0;
        }
#ifdef CONFIG_DIAG_SDIO_PIPE
        /* copy 9K data over SDIO */
        if (driver->in_busy_sdio == 1) {
            num_data++;
            /*Copy the length of data being passed*/
            COPY_USER_SPACE_OR_EXIT(buf+ret,
                                    (driver->write_ptr_mdm->length), 4);
            /*Copy the actual data being passed*/
            COPY_USER_SPACE_OR_EXIT(buf+ret,
                                    *(driver->buf_in_sdio),
                                    driver->write_ptr_mdm->length);
            driver->in_busy_sdio = 0;
        }
#endif
#ifdef CONFIG_DIAG_BRIDGE_CODE
        spin_lock_irqsave(&driver->hsic_spinlock, spin_lock_flags);
        for (i = 0; i < driver->poolsize_hsic_write; i++) {
            hsic_buf_tbl[i].buf = driver->hsic_buf_tbl[i].buf;
            driver->hsic_buf_tbl[i].buf = 0;
            hsic_buf_tbl[i].length =
                driver->hsic_buf_tbl[i].length;
            driver->hsic_buf_tbl[i].length = 0;
        }
        driver->num_hsic_buf_tbl_entries = 0;
        spin_unlock_irqrestore(&driver->hsic_spinlock,
                               spin_lock_flags);

        for (i = 0; i < driver->poolsize_hsic_write; i++) {
            if (hsic_buf_tbl[i].length > 0) {
                pr_debug("diag: HSIC copy to user, i: %d, buf: %x, len: %d\n",
                         i, (unsigned int)hsic_buf_tbl[i].buf,
                         hsic_buf_tbl[i].length);
                num_data++;
                /* Copy the length of data being passed */
                if (copy_to_user(buf+ret,
                                 (void *)&(hsic_buf_tbl[i].length),
                                 4)) {
                    num_data--;
                    goto drop_hsic;
                }
                ret += 4;

                /* Copy the actual data being passed */
                if (copy_to_user(buf+ret,
                                 (void *)hsic_buf_tbl[i].buf,
                                 hsic_buf_tbl[i].length)) {
                    ret -= 4;
                    num_data--;
                    goto drop_hsic;
                }
                ret += hsic_buf_tbl[i].length;
drop_hsic:
                /* Return the buffer to the pool */
                diagmem_free(driver,
                             (unsigned char *)(hsic_buf_tbl[i].buf),
                             POOL_TYPE_HSIC);

                /* Call the write complete function */
                diagfwd_write_complete_hsic(NULL);
            }
        }
#endif
        /* copy number of data fields */
        COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4);
        ret -= 4;
        driver->data_ready[index] ^= USER_SPACE_LOG_TYPE;
        if (driver->ch)
            queue_work(driver->diag_wq,
                       &(driver->diag_read_smd_work));
        if (driver->chqdsp)
            queue_work(driver->diag_wq,
                       &(driver->diag_read_smd_qdsp_work));
        if (driver->ch_wcnss)
            queue_work(driver->diag_wq,
                       &(driver->diag_read_smd_wcnss_work));
#ifdef CONFIG_DIAG_SDIO_PIPE
        if (driver->sdio_ch)
            queue_work(driver->diag_sdio_wq,
                       &(driver->diag_read_sdio_work));
#endif
        APPEND_DEBUG('n');
        goto exit;
    } else if (driver->data_ready[index] & USER_SPACE_LOG_TYPE) {
        /* In case, the thread wakes up and the logging mode is
        not memory device any more, the condition needs to be cleared */
        driver->data_ready[index] ^= USER_SPACE_LOG_TYPE;
    }

    if (driver->data_ready[index] & DEINIT_TYPE) {
        /*Copy the type of data being passed*/
        data_type = driver->data_ready[index] & DEINIT_TYPE;
        COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
        driver->data_ready[index] ^= DEINIT_TYPE;
        goto exit;
    }

    if (driver->data_ready[index] & MSG_MASKS_TYPE) {
        /*Copy the type of data being passed*/
        data_type = driver->data_ready[index] & MSG_MASKS_TYPE;
        COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
        COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->msg_masks),
                                MSG_MASK_SIZE);
        driver->data_ready[index] ^= MSG_MASKS_TYPE;
        goto exit;
    }

    if (driver->data_ready[index] & EVENT_MASKS_TYPE) {
        /*Copy the type of data being passed*/
        data_type = driver->data_ready[index] & EVENT_MASKS_TYPE;
        COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
        COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->event_masks),
                                EVENT_MASK_SIZE);
        driver->data_ready[index] ^= EVENT_MASKS_TYPE;
        goto exit;
    }

    if (driver->data_ready[index] & LOG_MASKS_TYPE) {
        /*Copy the type of data being passed*/
        data_type = driver->data_ready[index] & LOG_MASKS_TYPE;
        COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
        COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->log_masks),
                                LOG_MASK_SIZE);
        driver->data_ready[index] ^= LOG_MASKS_TYPE;
        goto exit;
    }

    if (driver->data_ready[index] & PKT_TYPE) {
        /*Copy the type of data being passed*/
        data_type = driver->data_ready[index] & PKT_TYPE;
        COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
        COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->pkt_buf),
                                driver->pkt_length);
        driver->data_ready[index] ^= PKT_TYPE;
        goto exit;
    }

    if (driver->data_ready[index] & DCI_DATA_TYPE) {
        /*Copy the type of data being passed*/
        data_type = driver->data_ready[index] & DCI_DATA_TYPE;
        COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
        COPY_USER_SPACE_OR_EXIT(buf+4,
                                driver->write_ptr_dci->length, 4);
        /* check delayed vs immediate response */
        if (*(uint8_t *)(driver->buf_in_dci+4) == DCI_CMD_CODE)
            COPY_USER_SPACE_OR_EXIT(buf+8,
                                    *(driver->buf_in_dci + 5), driver->write_ptr_dci->length);
        else
            COPY_USER_SPACE_OR_EXIT(buf+8,
                                    *(driver->buf_in_dci + 8), driver->write_ptr_dci->length);
        driver->in_busy_dci = 0;
        driver->data_ready[index] ^= DCI_DATA_TYPE;
        if (driver->ch_dci)
            queue_work(driver->diag_wq,
                       &(driver->diag_read_smd_dci_work));
        goto exit;
    }
exit:
    mutex_unlock(&driver->diagchar_mutex);
    return ret;
}
コード例 #4
0
static int diagcharmdm_read(struct file *file, char __user *buf, size_t count,
			  loff_t *ppos)
{

	int index = -1, i = 0, ret = 0;
	int num_data = 0, data_type;
#if defined(CONFIG_MACH_MECHA)

	if (!sdio_diag_initialized) {
		DIAG_INFO("sdio diag isn't in embedded mode \n");
		return 0;
	}
#endif
#ifdef DIAG_DEBUG
	DIAG_INFO("%s:%s(parent:%s): tgid=%d\n", __func__,
	current->comm, current->parent->comm, current->tgid);
#endif
	for (i = 0; i < driver->num_mdmclients; i++)
		if (driver->mdmclient_map[i].pid == current->tgid)
			index = i;

	if (index == -1) {
		DIAG_ERR("\n Client PID not found in table");
		return -EINVAL;
	}

	wait_event_interruptible(driver->mdmwait_q,
				  driver->mdmdata_ready[index]);

	mutex_lock(&driver->diagcharmdm_mutex);

	if ((driver->mdmdata_ready[index] & MEMORY_DEVICE_LOG_TYPE) && (driver->
					logging_mode == MEMORY_DEVICE_MODE)) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & MEMORY_DEVICE_LOG_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		/* place holder for number of data field */
		ret += 4;
#if defined(CONFIG_MACH_MECHA)
		/* copy modem data */
		if (driver->in_busy_mdm_1 == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					 (driver->write_ptr_mdm_1->length), 4);

			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					*(driver->buf_in_mdm_1),
					 driver->write_ptr_mdm_1->length);
			driver->in_busy_mdm_1 = 0;
		}
		if (driver->in_busy_mdm_2 == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					 (driver->write_ptr_mdm_2->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					 *(driver->buf_in_mdm_2),
					 driver->write_ptr_mdm_2->length);
			driver->in_busy_mdm_2 = 0;
		}
#endif
#ifdef CONFIG_ARCH_MSM8X60_LTE
		if (driver->in_busy_sdio_1 == 1) {

			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
				 (driver->write_ptr_mdm_1->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
				buf_in_sdio_1), driver->
					write_ptr_mdm_1->length);
			driver->in_busy_sdio_1 = 0;
		}
		if (driver->in_busy_sdio_2 == 1) {

			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
				 (driver->write_ptr_mdm_2->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
				buf_in_sdio_2), driver->
					write_ptr_mdm_2->length);
			driver->in_busy_sdio_2 = 0;
		}
#endif
		/* copy number of data fields */
		COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4);
		ret -= 4;

		driver->mdmdata_ready[index] ^= MEMORY_DEVICE_LOG_TYPE;
#ifdef CONFIG_MACH_MECHA
		queue_work(driver->mdm_diag_workqueue, &(driver->diag_read_smd_mdm_work));
#endif
#ifdef CONFIG_ARCH_MSM8X60_LTE
			if (driver->sdio_ch)
			queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work));
#endif
		goto exit;
	} else if (driver->mdmdata_ready[index] & MEMORY_DEVICE_LOG_TYPE) {
		/* In case, the thread wakes up and the logging mode is
		not memory device any more, the condition needs to be cleared */
		driver->mdmdata_ready[index] ^= MEMORY_DEVICE_LOG_TYPE;
	}
#ifdef CONFIG_ARCH_MSM8X60_LTE
	else if (driver->mdmdata_ready[index] & USERMODE_DIAGFWD) {
		data_type = USERMODE_DIAGFWD;
		driver->mdmdata_ready[index] ^= USERMODE_DIAGFWD;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);

		if (driver->in_busy_sdio_1 == 1) {
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
				buf_in_sdio_1), driver->
					write_ptr_mdm_1->length);
			driver->in_busy_sdio_1 = 0;
		}
		if (driver->in_busy_sdio_2 == 1) {
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
				buf_in_sdio_2), driver->
					write_ptr_mdm_2->length);
			driver->in_busy_sdio_2 = 0;
		}
		if (driver->sdio_ch)
		queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work));
		goto exit;
	}
#endif
	if (driver->mdmdata_ready[index] & DEINIT_TYPE) {

		driver->mdmdata_ready[index] ^= DEINIT_TYPE;
		goto exit;
	}

	if (driver->mdmdata_ready[index] & MSG_MASKS_TYPE) {

		driver->mdmdata_ready[index] ^= MSG_MASKS_TYPE;
		goto exit;
	}

	if (driver->mdmdata_ready[index] & EVENT_MASKS_TYPE) {

		driver->mdmdata_ready[index] ^= EVENT_MASKS_TYPE;
		goto exit;
	}

	if (driver->mdmdata_ready[index] & LOG_MASKS_TYPE) {

		driver->mdmdata_ready[index] ^= LOG_MASKS_TYPE;
		goto exit;
	}

	if (driver->mdmdata_ready[index] & PKT_TYPE) {

		driver->mdmdata_ready[index] ^= PKT_TYPE;
		goto exit;
	}
exit:
	mutex_unlock(&driver->diagcharmdm_mutex);

	return ret;

}
コード例 #5
0
static int diagchar_read(struct file *file, char __user *buf, size_t count,
			  loff_t *ppos)
{
	int index = -1, i = 0, ret = 0;
	int num_data = 0, data_type;
	for (i = 0; i < driver->num_clients; i++)
		if (driver->client_map[i].pid == current->tgid)
			index = i;

	if (index == -1) {
		printk(KERN_ALERT "\n Client PID not found in table");
		return -EINVAL;
	}

	wait_event_interruptible(driver->wait_q,
				  driver->data_ready[index]);
	mutex_lock(&driver->diagchar_mutex);

	if ((driver->data_ready[index] & MEMORY_DEVICE_LOG_TYPE) && (driver->
					logging_mode == MEMORY_DEVICE_MODE)) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & MEMORY_DEVICE_LOG_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		/* place holder for number of data field */
		ret += 4;

		for (i = 0; i < driver->poolsize_usb_struct; i++) {
			if (driver->buf_tbl[i].length > 0) {
#ifdef DIAG_DEBUG
				printk(KERN_INFO "\n WRITING the buf address "
				       "and length is %x , %d\n", (unsigned int)
					(driver->buf_tbl[i].buf),
					driver->buf_tbl[i].length);
#endif
				num_data++;
				/* Copy the length of data being passed */
				if (copy_to_user(buf+ret, (void *)&(driver->
						buf_tbl[i].length), 4)) {
						num_data--;
						goto drop;
				}
				ret += 4;

				/* Copy the actual data being passed */
				if (copy_to_user(buf+ret, (void *)driver->
				buf_tbl[i].buf, driver->buf_tbl[i].length)) {
					ret -= 4;
					num_data--;
					goto drop;
				}
				ret += driver->buf_tbl[i].length;
drop:
#ifdef DIAG_DEBUG
				printk(KERN_INFO "\n DEQUEUE buf address and"
				       " length is %x,%d\n", (unsigned int)
				       (driver->buf_tbl[i].buf), driver->
				       buf_tbl[i].length);
#endif
				diagmem_free(driver, (unsigned char *)
				(driver->buf_tbl[i].buf), POOL_TYPE_HDLC);
				driver->buf_tbl[i].length = 0;
				driver->buf_tbl[i].buf = 0;
			}
		}

		/* copy modem data */
		if (driver->in_busy == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
					 (driver->usb_write_ptr->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->usb_buf_in),
					 driver->usb_write_ptr->length);
			driver->in_busy = 0;
		}

		/* copy q6 data */
		if (driver->in_busy_qdsp == 1) {
			num_data++;
			/*Copy the length of data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret,
				 (driver->usb_write_ptr_qdsp->length), 4);
			/*Copy the actual data being passed*/
			COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
			usb_buf_in_qdsp), driver->usb_write_ptr_qdsp->length);
			driver->in_busy_qdsp = 0;
		}

		/* copy number of data fields */
		COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4);
		ret -= 4;
		driver->data_ready[index] ^= MEMORY_DEVICE_LOG_TYPE;
		if (driver->ch)
			queue_work(driver->diag_wq,
					 &(driver->diag_read_smd_work));
		if (driver->chqdsp)
			queue_work(driver->diag_wq,
					 &(driver->diag_read_smd_qdsp_work));
		APPEND_DEBUG('n');
		goto exit;
	} else if (driver->data_ready[index] & MEMORY_DEVICE_LOG_TYPE) {
		/* In case, the thread wakes up and the logging mode is
		not memory device any more, the condition needs to be cleared */
		driver->data_ready[index] ^= MEMORY_DEVICE_LOG_TYPE;
	}

	if (driver->data_ready[index] & DEINIT_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & DEINIT_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		driver->data_ready[index] ^= DEINIT_TYPE;
		goto exit;
	}

	if (driver->data_ready[index] & MSG_MASKS_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & MSG_MASKS_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->msg_masks),
							 MSG_MASK_SIZE);
		driver->data_ready[index] ^= MSG_MASKS_TYPE;
		goto exit;
	}

	if (driver->data_ready[index] & EVENT_MASKS_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & EVENT_MASKS_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->event_masks),
							 EVENT_MASK_SIZE);
		driver->data_ready[index] ^= EVENT_MASKS_TYPE;
		goto exit;
	}

	if (driver->data_ready[index] & LOG_MASKS_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & LOG_MASKS_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->log_masks),
							 LOG_MASK_SIZE);
		driver->data_ready[index] ^= LOG_MASKS_TYPE;
		goto exit;
	}

	if (driver->data_ready[index] & PKT_TYPE) {
		/*Copy the type of data being passed*/
		data_type = driver->data_ready[index] & PKT_TYPE;
		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
		COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->pkt_buf),
							 driver->pkt_length);
		driver->data_ready[index] ^= PKT_TYPE;
		/* LGE_CHANGE_S [[email protected]] 2010-11-22 - fix diag packet drop issue */
		driver->pkt_length = 0;
		/* LGE_CHANGE_E [[email protected]] 2010-11-22 */
		goto exit;
	}

exit:
	mutex_unlock(&driver->diagchar_mutex);
	return ret;
}