static void diagfwd_hsic_notifier(void *priv, unsigned event, struct diag_request *d_req) { switch (event) { case USB_DIAG_CONNECT: diagfwd_connect_hsic(); break; case USB_DIAG_DISCONNECT: diagfwd_disconnect_hsic(); break; case USB_DIAG_READ_DONE: diagfwd_read_complete_hsic(d_req); break; case USB_DIAG_WRITE_DONE: diagfwd_write_complete_hsic(); break; default: pr_err("DIAG in %s: Unknown event from USB diag:%u\n", __func__, event); break; } }
static void diag_disconnect_work_fn(struct work_struct *w) { diagfwd_disconnect_hsic(); }
long diagchar_ioctl(struct file *filp, unsigned int iocmd, unsigned long ioarg) { int i, j, count_entries = 0, temp; int success = -1; void *temp_buf; uint16_t support_list = 0; if (iocmd == DIAG_IOCTL_COMMAND_REG) { struct bindpkt_params_per_process *pkt_params = (struct bindpkt_params_per_process *) ioarg; mutex_lock(&driver->diagchar_mutex); for (i = 0; i < diag_max_reg; i++) { if (driver->table[i].process_id == 0) { diag_add_reg(i, pkt_params->params, &success, &count_entries); if (pkt_params->count > count_entries) { pkt_params->params++; } else { mutex_unlock(&driver->diagchar_mutex); return success; } } } if (i < diag_threshold_reg) { /* Increase table size by amount required */ diag_max_reg += pkt_params->count - count_entries; /* Make sure size doesnt go beyond threshold */ if (diag_max_reg > diag_threshold_reg) { diag_max_reg = diag_threshold_reg; pr_info("diag: best case memory allocation\n"); } temp_buf = krealloc(driver->table, diag_max_reg*sizeof(struct diag_master_table), GFP_KERNEL); if (!temp_buf) { diag_max_reg -= pkt_params->count - count_entries; pr_alert("diag: Insufficient memory for reg."); mutex_unlock(&driver->diagchar_mutex); return 0; } else { driver->table = temp_buf; } for (j = i; j < diag_max_reg; j++) { diag_add_reg(j, pkt_params->params, &success, &count_entries); if (pkt_params->count > count_entries) { pkt_params->params++; } else { mutex_unlock(&driver->diagchar_mutex); return success; } } mutex_unlock(&driver->diagchar_mutex); } else { mutex_unlock(&driver->diagchar_mutex); pr_err("Max size reached, Pkt Registration failed for" " Process %d", current->tgid); } success = 0; } else if (iocmd == DIAG_IOCTL_GET_DELAYED_RSP_ID) { struct diagpkt_delay_params *delay_params = (struct diagpkt_delay_params *) ioarg; if ((delay_params->rsp_ptr) && (delay_params->size == sizeof(delayed_rsp_id)) && (delay_params->num_bytes_ptr)) { *((uint16_t *)delay_params->rsp_ptr) = DIAGPKT_NEXT_DELAYED_RSP_ID(delayed_rsp_id); *(delay_params->num_bytes_ptr) = sizeof(delayed_rsp_id); success = 0; } } else if (iocmd == DIAG_IOCTL_DCI_REG) { if (driver->dci_state == DIAG_DCI_NO_REG) return DIAG_DCI_NO_REG; /* use the 'list' later on to notify user space */ if (driver->num_dci_client >= MAX_DCI_CLIENT) return DIAG_DCI_NO_REG; mutex_lock(&driver->dci_mutex); driver->num_dci_client++; pr_debug("diag: id = %d\n", driver->dci_client_id); driver->dci_client_id++; mutex_unlock(&driver->dci_mutex); return driver->dci_client_id; } else if (iocmd == DIAG_IOCTL_DCI_DEINIT) { success = -1; /* Delete this process from DCI table */ mutex_lock(&driver->dci_mutex); for (i = 0; i < dci_max_reg; i++) { if (driver->dci_tbl[i].pid == current->tgid) { pr_debug("diag: delete %d\n", current->tgid); driver->dci_tbl[i].pid = 0; success = i; } } /* if any registrations were deleted successfully OR a valid client_id was sent in DEINIT call , then its DCI client */ if (success >= 0 || ioarg) driver->num_dci_client--; driver->num_dci_client--; mutex_unlock(&driver->dci_mutex); for (i = 0; i < dci_max_reg; i++) if (driver->dci_tbl[i].pid != 0) pr_debug("diag: PID = %d, UID = %d, tag = %d\n", driver->dci_tbl[i].pid, driver->dci_tbl[i].uid, driver->dci_tbl[i].tag); pr_debug("diag: complete deleting registrations\n"); return success; } else if (iocmd == DIAG_IOCTL_DCI_SUPPORT) { if (driver->ch_dci) support_list = support_list | DIAG_CON_MPSS; *(uint16_t *)ioarg = support_list; return DIAG_DCI_NO_ERROR; } else if (iocmd == DIAG_IOCTL_LSM_DEINIT) { for (i = 0; i < driver->num_clients; i++) if (driver->client_map[i].pid == current->tgid) break; if (i == -1) return -EINVAL; driver->data_ready[i] |= DEINIT_TYPE; wake_up_interruptible(&driver->wait_q); success = 1; } else if (iocmd == DIAG_IOCTL_SWITCH_LOGGING) { mutex_lock(&driver->diagchar_mutex); temp = driver->logging_mode; driver->logging_mode = (int)ioarg; if (driver->logging_mode == MEMORY_DEVICE_MODE) driver->mask_check = 1; if (driver->logging_mode == UART_MODE) { driver->mask_check = 0; driver->logging_mode = MEMORY_DEVICE_MODE; } driver->logging_process_id = current->tgid; mutex_unlock(&driver->diagchar_mutex); if (temp == MEMORY_DEVICE_MODE && driver->logging_mode == NO_LOGGING_MODE) { driver->in_busy_1 = 1; driver->in_busy_2 = 1; driver->in_busy_qdsp_1 = 1; driver->in_busy_qdsp_2 = 1; driver->in_busy_wcnss_1 = 1; driver->in_busy_wcnss_2 = 1; #ifdef CONFIG_DIAG_SDIO_PIPE driver->in_busy_sdio = 1; #endif #ifdef CONFIG_DIAG_HSIC_PIPE diagfwd_disconnect_hsic(0); #endif } else if (temp == NO_LOGGING_MODE && driver->logging_mode == MEMORY_DEVICE_MODE) { driver->in_busy_1 = 0; driver->in_busy_2 = 0; driver->in_busy_qdsp_1 = 0; driver->in_busy_qdsp_2 = 0; driver->in_busy_wcnss_1 = 0; driver->in_busy_wcnss_2 = 0; /* Poll SMD channels to check for data*/ 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 driver->in_busy_sdio = 0; /* Poll SDIO channel to check for data */ if (driver->sdio_ch) queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work)); #endif #ifdef CONFIG_DIAG_HSIC_PIPE diagfwd_connect_hsic(0); #endif } #ifdef CONFIG_DIAG_OVER_USB else if (temp == USB_MODE && driver->logging_mode == NO_LOGGING_MODE) { diagfwd_disconnect(); #ifdef CONFIG_DIAG_HSIC_PIPE diagfwd_disconnect_hsic(0); #endif } else if (temp == NO_LOGGING_MODE && driver->logging_mode == USB_MODE) { diagfwd_connect(); #ifdef CONFIG_DIAG_HSIC_PIPE diagfwd_connect_hsic(0); #endif } else if (temp == USB_MODE && driver->logging_mode == MEMORY_DEVICE_MODE) { diagfwd_disconnect(); driver->in_busy_1 = 0; driver->in_busy_2 = 0; driver->in_busy_qdsp_1 = 0; driver->in_busy_qdsp_2 = 0; driver->in_busy_wcnss_1 = 0; driver->in_busy_wcnss_2 = 0; /* Poll SMD channels to check for data*/ 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 driver->in_busy_sdio = 0; /* Poll SDIO channel to check for data */ if (driver->sdio_ch) queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work)); #endif #ifdef CONFIG_DIAG_HSIC_PIPE diagfwd_cancel_hsic(); diagfwd_connect_hsic(0); #endif } else if (temp == MEMORY_DEVICE_MODE && driver->logging_mode == USB_MODE) { diagfwd_connect(); #ifdef CONFIG_DIAG_HSIC_PIPE diagfwd_cancel_hsic(); diagfwd_connect_hsic(0); #endif } #endif /* DIAG over USB */ success = 1; } return success; }
static int lge_dm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { short modem_number, result; struct dm_tty *lge_dm_tty_drv = NULL; int is_all_closed, i; lge_dm_tty_drv = lge_dm_tty; tty->driver_data = lge_dm_tty_drv; lge_dm_tty_drv->tty_str = tty; if (_IOC_TYPE(cmd) != DM_TTY_IOCTL_MAGIC) return -EINVAL; switch (cmd) { case DM_TTY_MODEM_OPEN: if (copy_from_user((void *)&modem_number, (const void *)arg, sizeof(modem_number)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_IOCTL_MODEM_OPEN modem_number = %d\n", __func__, modem_number); if (lge_dm_tty_drv->is_modem_open[modem_number] == FALSE) lge_dm_tty_drv->is_modem_open[modem_number] = TRUE; else pr_err(DM_TTY_MODULE_NAME ": %s: already open " "modem_number = %d", __func__, modem_number); diagfwd_disconnect(); #ifdef CONFIG_DIAG_HSIC_PIPE diagfwd_disconnect_hsic(1); diagfwd_cancel_hsic(); diagfwd_connect_hsic(0); #endif /* change path to DM APP */ mutex_lock(&driver->diagchar_mutex); driver->logging_mode = DM_APP_MODE; mutex_unlock(&driver->diagchar_mutex); if (modem_number == Primary_modem_chip) { driver->in_busy_1 = 0; driver->in_busy_2 = 0; driver->in_busy_qdsp_1 = 0; driver->in_busy_qdsp_2 = 0; driver->in_busy_wcnss_1 = 0; driver->in_busy_wcnss_2 = 0; /* Poll SMD channels to check for data*/ 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)); } else if (modem_number == Secondary_modem_chip) { #ifdef CONFIG_DIAG_SDIO_PIPE driver->in_busy_sdio = 0; /* Poll SDIO channel to check for data */ if (driver->sdio_ch) queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work)); #endif #ifdef CONFIG_DIAG_HSIC_PIPE driver->num_hsic_buf_tbl_entries = 0; for (i = 0; i < driver->poolsize_hsic_write; i++) { driver->hsic_buf_tbl[i].buf = 0; driver->hsic_buf_tbl[i].length = 0; } #endif } else { pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_IOCTL_MODEM_OPEN" "error modem_number = %d\n", __func__, modem_number); } result = lge_dm_tty_drv->is_modem_open[modem_number]; if (copy_to_user((void *)arg, (const void *)&result, sizeof(result)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_IOCTL_MODEM_OPEN" "result = %d\n", __func__, result); break; case DM_TTY_MODEM_CLOSE: if (copy_from_user((void *)&modem_number, (const void *)arg, sizeof(modem_number)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_IOCTL_MODEM_CLOSE modem_number = %d\n", __func__, modem_number); if (modem_number == 0) { /* close all modem chip */ for (i = 0; i < NUM_MODEM_CHIP + 1; i++) lge_dm_tty_drv->is_modem_open[i] = FALSE; result = TRUE; pr_err(DM_TTY_MODULE_NAME ": %s: close all modem chip" , __func__); } else { if (lge_dm_tty_drv->is_modem_open[modem_number] == TRUE) lge_dm_tty_drv->is_modem_open[modem_number] = FALSE; else pr_err(DM_TTY_MODULE_NAME ": %s: " "already closed " "modem_number = %d", __func__, modem_number); /* check all modem chip closed */ is_all_closed = TRUE; for (i = 0; i < NUM_MODEM_CHIP + 1; i++) { if (lge_dm_tty_drv->is_modem_open[i] == TRUE) is_all_closed = FALSE; } result = is_all_closed; } if (result == TRUE) { lge_dm_tty->set_logging = 0; /* change path to USB driver */ mutex_lock(&driver->diagchar_mutex); driver->logging_mode = USB_MODE; mutex_unlock(&driver->diagchar_mutex); if (driver->usb_connected == 0) diagfwd_disconnect(); else diagfwd_connect(); #ifdef CONFIG_DIAG_HSIC_PIPE driver->num_hsic_buf_tbl_entries = 0; for (i = 0; i < driver->poolsize_hsic_write; i++) { if (driver->hsic_buf_tbl[i].buf) { /* Return the buffer to the pool */ diagmem_free(driver, (unsigned char *) (driver->hsic_buf_tbl[i].buf), POOL_TYPE_HSIC); driver->hsic_buf_tbl[i].buf = 0; driver->hsic_buf_tbl[i].length = 0; } } if (driver->usb_mdm_connected == 0) diagfwd_disconnect_hsic(0); else diagfwd_connect_hsic(0); #endif } if (copy_to_user((void *)arg, (const void *)&result, sizeof(result)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_IOCTL_MODEM_CLOSE" "result = %d\n", __func__, result); break; case DM_TTY_MODEM_STATUS: if (copy_from_user((void *)&modem_number, (const void *)arg, sizeof(modem_number)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_IOCTL_MODEM_STATUS modem_number = %d\n", __func__, modem_number); result = lge_dm_tty_drv->is_modem_open[modem_number]; if (copy_to_user((void *)arg, (const void *)&result, sizeof(result)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_IOCTL_MODEM_STATUS" "result = %d\n", __func__, result); break; case DM_TTY_DATA_TO_APP: if (copy_from_user((void *)&modem_number, (const void *)arg, sizeof(modem_number)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_IOCTL_DATA_TO_APP modem_number = %d\n", __func__, modem_number); if (copy_to_user((void *)arg, (const void*)&result, sizeof(result)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_IOCTL_DATA_TO_APP" "result = %d\n", __func__, result); break; case DM_TTY_DATA_TO_USB: if (copy_from_user((void *)&modem_number, (const void *)arg, sizeof(modem_number)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_IOCTL_DATA_TO_USB" "modem_number = %d\n", __func__, modem_number); if (copy_to_user((void *)arg, (const void *)&result, sizeof(result)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_IOCTL_DATA_TO_USB" "result = %d\n", __func__, result); break; default: pr_info(DM_TTY_MODULE_NAME ": %s:" "lge_dm_tty_ioctl error\n", __func__); break; } return 0; }