int diag_device_write(void *buf, int proc_num) { int i, err = 0; if (driver->logging_mode == USB_MODE) { if (proc_num == APPS_DATA) { driver->usb_write_ptr_svc = (struct diag_request *) (diagmem_alloc(driver, sizeof(struct diag_request), POOL_TYPE_USB_STRUCT)); if (!driver->usb_write_ptr_svc) return -ENOMEM; driver->usb_write_ptr_svc->length = driver->used; driver->usb_write_ptr_svc->buf = buf; err = diag_write(driver->usb_write_ptr_svc); } else if (proc_num == MODEM_DATA) { driver->usb_write_ptr->buf = buf; #ifdef DIAG_DEBUG printk(KERN_INFO "writing data to USB," " pkt length %d \n", driver->usb_write_ptr->length); print_hex_dump(KERN_DEBUG, "Written Packet Data" " to USB: ", 16, 1, DUMP_PREFIX_ ADDRESS, buf, driver-> usb_write_ptr->length, 1); #endif err = diag_write(driver->usb_write_ptr); } else if (proc_num == QDSP_DATA) { driver->usb_write_ptr_qdsp->buf = buf; err = diag_write(driver->usb_write_ptr_qdsp); } APPEND_DEBUG('k'); } else if (driver->logging_mode == MEMORY_DEVICE_MODE) { if (proc_num == APPS_DATA) { for (i = 0; i < driver->poolsize_usb_struct; i++) if (driver->buf_tbl[i].length == 0) { driver->buf_tbl[i].buf = buf; driver->buf_tbl[i].length = driver->used; #ifdef DIAG_DEBUG printk(KERN_INFO "\n ENQUEUE buf ptr" " and length is %x , %d\n", (unsigned int)(driver->buf_ tbl[i].buf), driver->buf_tbl[i].length); #endif break; } } for (i = 0; i < driver->num_clients; i++) if (driver->client_map[i].pid == driver->logging_process_id) break; if (i < driver->num_clients) { driver->data_ready[i] |= MEMORY_DEVICE_LOG_TYPE; wake_up_interruptible(&driver->wait_q); } else return -EINVAL; } else if (driver->logging_mode == NO_LOGGING_MODE) { if (proc_num == MODEM_DATA) { driver->in_busy = 0; queue_work(driver->diag_wq, &(driver-> diag_read_smd_work)); } else if (proc_num == QDSP_DATA) { driver->in_busy_qdsp = 0; queue_work(driver->diag_wq, &(driver-> diag_read_smd_qdsp_work)); } err = -1; } return err; }
int diag_device_write(void *buf, int proc_num, struct diag_request *write_ptr) { int i, err = 0; if (driver->logging_mode == MEMORY_DEVICE_MODE) { if (proc_num == APPS_DATA) { for (i = 0; i < driver->poolsize_write_struct; i++) if (driver->buf_tbl[i].length == 0) { driver->buf_tbl[i].buf = buf; driver->buf_tbl[i].length = driver->used; #ifdef DIAG_DEBUG printk(KERN_INFO "\n ENQUEUE buf ptr" " and length is %x , %d\n", (unsigned int)(driver->buf_ tbl[i].buf), driver->buf_tbl[i].length); #endif break; } } for (i = 0; i < driver->num_clients; i++) if (driver->client_map[i].pid == driver->logging_process_id) break; if (i < driver->num_clients) { driver->data_ready[i] |= MEMORY_DEVICE_LOG_TYPE; wake_up_interruptible(&driver->wait_q); } else return -EINVAL; } else if (driver->logging_mode == NO_LOGGING_MODE) { if (proc_num == MODEM_DATA) { driver->in_busy_1 = 0; driver->in_busy_2 = 0; queue_work(driver->diag_wq, &(driver-> diag_read_smd_work)); } else if (proc_num == QDSP_DATA) { driver->in_busy_qdsp_1 = 0; driver->in_busy_qdsp_2 = 0; queue_work(driver->diag_wq, &(driver-> diag_read_smd_qdsp_work)); } err = -1; } #ifdef CONFIG_DIAG_OVER_USB else if (driver->logging_mode == USB_MODE) { if (proc_num == APPS_DATA) { driver->write_ptr_svc = (struct diag_request *) (diagmem_alloc(driver, sizeof(struct diag_request), POOL_TYPE_WRITE_STRUCT)); if (driver->write_ptr_svc) { driver->write_ptr_svc->length = driver->used; driver->write_ptr_svc->buf = buf; #ifdef CONFIG_SH_USB_CUST err = diag_write(driver->write_ptr_svc); #else /* CONFIG_SH_USB_CUST */ err = usb_diag_write(driver->legacy_ch, driver->write_ptr_svc); #endif /* CONFIG_SH_USB_CUST */ } else err = -1; } else if (proc_num == MODEM_DATA) { write_ptr->buf = buf; #ifdef DIAG_DEBUG printk(KERN_INFO "writing data to USB," "pkt length %d\n", write_ptr->length); print_hex_dump(KERN_DEBUG, "Written Packet Data to" " USB: ", 16, 1, DUMP_PREFIX_ADDRESS, buf, write_ptr->length, 1); #endif /* DIAG DEBUG */ #ifdef CONFIG_SH_USB_CUST err = diag_write(write_ptr); #else /* CONFIG_SH_USB_CUST */ err = usb_diag_write(driver->legacy_ch, write_ptr); #endif /* CONFIG_SH_USB_CUST */ } else if (proc_num == QDSP_DATA) { write_ptr->buf = buf; #ifdef CONFIG_SH_USB_CUST err = diag_write(write_ptr); #else /* CONFIG_SH_USB_CUST */ err = usb_diag_write(driver->legacy_ch, write_ptr); #endif /* CONFIG_SH_USB_CUST */ } #ifdef CONFIG_DIAG_SDIO_PIPE else if (proc_num == SDIO_DATA) { /* COORDINATOR Qualcomm4040 MERGE start */ #ifdef CONFIG_SH_USB_CUST write_ptr->buf = buf; diag_write(write_ptr); #else /* CONFIG_SH_USB_CUST */ if (machine_is_msm8x60_charm_surf() || machine_is_msm8x60_charm_ffa()) { write_ptr->buf = buf; err = usb_diag_write(driver->mdm_ch, write_ptr); } else pr_err("diag: Incorrect data while USB write"); #endif /* CONFIG_SH_USB_CUST */ /* COORDINATOR Qualcomm4040 MERGE end */ } #endif APPEND_DEBUG('d'); } #endif /* DIAG OVER USB */ return err; }
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 for (i = 0; i < driver->num_clients; i++) if (driver->client_map[i].pid == current->tgid) index = i; if (index == -1) { DIAG_ERR("%s:%s(parent:%s): tgid=%d" "Client PID not found in table\n", __func__, current->comm, current->parent->comm, current->tgid); for (i = 0; i < driver->num_clients; i++) DIAG_ERR("\t#%d: %d\n", i, driver->client_map[i].pid); return -EINVAL; } wait_event_interruptible(driver->wait_q, driver->data_ready[index]); if (diag7k_debug_mask) DIAG_INFO("%s:%s(parent:%s): tgid=%d\n", __func__, current->comm, current->parent->comm, current->tgid); 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; } /* 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)); 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; } 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 for (i = 0; i < driver->poolsize_write_struct; i++) { if (driver->buf_tbl[i].length > 0) { #ifdef SDQXDM_DEBUG if (diag7k_debug_mask) 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 if (copy_to_user(buf+ret, (void *)driver-> buf_tbl[i].buf, driver->buf_tbl[i].length)) break; ret += driver->buf_tbl[i].length; 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) { /*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; } /* copy wncss data */ if (driver->in_busy_wcnss == 1) { /*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; } 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)); if (diag7k_debug_mask) pr_info("%s() return %d byte\n", __func__, ret); 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; }
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; }
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_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; } #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] ^= 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)); #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] & 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; goto exit; } exit: mutex_unlock(&driver->diagchar_mutex); return ret; }
void diag_process_hdlc(void *data, unsigned len) { struct diag_hdlc_decode_type hdlc; int ret, type = 0; #ifdef CONFIG_LGE_DIAG unsigned int nTempLen = 0; #endif // LGE_CHANGE [2011.07.22] M3S : for remove compile warnig //#if defined(DIAG_DEBUG) || defined(CONFIG_DIAG_OVER_USB) #if defined(DIAG_DEBUD) int i; pr_debug("\n HDLC decode function, len of data %d\n", len); #endif hdlc.dest_ptr = driver->hdlc_buf; hdlc.dest_size = USB_MAX_OUT_BUF; hdlc.src_ptr = data; hdlc.src_size = len; hdlc.src_idx = 0; hdlc.dest_idx = 0; hdlc.escaping = 0; #ifdef CONFIG_LGE_DIAG if( len > 2 ) { if( hdlc.src_ptr[len -1] == 0x7E && hdlc.src_ptr[len -2] == 0x7E) { len--; hdlc.src_size--; } } do { ret = diag_hdlc_decode(&hdlc); nTempLen = hdlc.dest_idx; if(ret) { hdlc.dest_idx = 0; /* Initialize for the next packet */ } if( hdlc.src_idx >= hdlc.src_size) { //ret = 1; break; } else { if(nTempLen > 1) break; ret = 0; } }while ( ret == 0 ); if (ret) { type = diag_process_apps_pkt(driver->hdlc_buf, nTempLen - 3); } /* ignore 2 bytes for CRC, one for 7E and send */ if ((driver->ch) && (ret) && (type) && (nTempLen > 3)) { smd_write(driver->ch, driver->hdlc_buf, nTempLen - 3); #ifdef DIAG_DEBUG printk(KERN_INFO "writing data to SMD, pkt length %d\n", len); print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16, 1, DUMP_PREFIX_ADDRESS, data, len, 1); #endif /* DIAG DEBUG */ } #else /*CONFIG_LGE_DIAG*/ ret = diag_hdlc_decode(&hdlc); if (ret) type = diag_process_apps_pkt(driver->hdlc_buf, hdlc.dest_idx - 3); else if (driver->debug_flag) { printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC" " errors or partial packet received, packet" " length = %d\n", len); print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1, DUMP_PREFIX_ADDRESS, data, len, 1); driver->debug_flag = 0; } /* implies this packet is NOT meant for apps */ if (!(driver->ch) && type == 1 && chk_config_get_id()) { if (chk_config_get_id() == AO8960_TOOLS_ID) { #if defined(CONFIG_DIAG_OVER_USB) driver->apps_rsp_buf[0] = 0x13; for (i = 0; i < hdlc.dest_idx; i++) driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i); ENCODE_RSP_AND_SEND(hdlc.dest_idx - 3); #endif } else { /* APQ 8060, Let Q6 respond */ if (driver->chqdsp) smd_write(driver->chqdsp, driver->hdlc_buf, hdlc.dest_idx - 3); } type = 0; } #ifdef DIAG_DEBUG printk(KERN_INFO "\n hdlc.dest_idx = %d", hdlc.dest_idx); for (i = 0; i < hdlc.dest_idx; i++) printk(KERN_DEBUG "\t%x", *(((unsigned char *) driver->hdlc_buf)+i)); #endif /* DIAG DEBUG */ /* ignore 2 bytes for CRC, one for 7E and send */ if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) { APPEND_DEBUG('g'); smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3); APPEND_DEBUG('h'); #ifdef DIAG_DEBUG printk(KERN_INFO "writing data to SMD, pkt length %d\n", len); print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16, 1, DUMP_PREFIX_ADDRESS, data, len, 1); #endif /* DIAG DEBUG */ } #endif /*CONFIG_LGE_DIAG*/ }
void __diag_sdio_send_req(void) { int r = 0; void *buf = NULL; int *in_busy_ptr = NULL; struct diag_request *write_ptr_modem = NULL; int retry = 0; #if defined(CONFIG_MACH_VIGOR) int type; #endif if (!driver->in_busy_sdio_1) { buf = driver->buf_in_sdio_1; write_ptr_modem = driver->write_ptr_mdm_1; in_busy_ptr = &(driver->in_busy_sdio_1); } else if (!driver->in_busy_sdio_2) { buf = driver->buf_in_sdio_2; write_ptr_modem = driver->write_ptr_mdm_2; in_busy_ptr = &(driver->in_busy_sdio_2); } APPEND_DEBUG('Z'); if (driver->sdio_ch && buf) { r = sdio_read_avail(driver->sdio_ch); if (r > MAX_IN_BUF_SIZE) { DIAG_ERR("\n diag: SDIO sending" " in packets more than %d bytes\n", r); } if (r > 0) { if (!buf) DIAG_INFO("Out of diagmem for SDIO\n"); else { drop: APPEND_DEBUG('i'); sdio_read(driver->sdio_ch, buf, r); if ((driver->qxdm2sd_drop) && (driver->logging_mode == USB_MODE)) { /*Drop the diag payload */ DIAG_INFO("%s:Drop the diag payload :%d\n", __func__, retry); print_hex_dump(KERN_DEBUG, "Drop Packet Data" " from 9K(first 16 bytes)", DUMP_PREFIX_ADDRESS, 16, 1, buf, 16, 1); driver->in_busy_sdio_1 = 0; driver->in_busy_sdio_2 = 0; r=sdio_read_avail(driver->sdio_ch); if (++retry > 20) { driver->qxdm2sd_drop = 0; return; } if (r) goto drop; else { driver->qxdm2sd_drop = 0; return; } } APPEND_DEBUG('j'); if (diag9k_debug_mask) { switch (diag9k_debug_mask) { case 1: print_hex_dump(KERN_DEBUG, "Read Packet Data" " from 9K(first 16 bytes)", DUMP_PREFIX_ADDRESS, 16, 1, buf, 16, 1); break; case 2: print_hex_dump(KERN_DEBUG, "Read Packet Data" " from 9K(first 16 bytes)", DUMP_PREFIX_ADDRESS, 16, 1, buf, 16, 1); print_hex_dump(KERN_DEBUG, "Read Packet Data" " from 9K(last 16 bytes) ", 16, 1, DUMP_PREFIX_ADDRESS, buf+r-16, 16, 1); break; default: print_hex_dump(KERN_DEBUG, "Read Packet Data" " from 9K ", DUMP_PREFIX_ADDRESS, 16, 1, buf, r, 1); } } #if defined(CONFIG_MACH_VIGOR) type = checkcmd_modem_epst(buf); if (type) { modem_to_userspace(buf, r, type, 1); return; } #endif write_ptr_modem->length = r; *in_busy_ptr = 1; diag_device_write(buf, SDIO_DATA, write_ptr_modem); } } } }
int diag_device_write(void *buf, int proc_num, struct diag_request *write_ptr) { int i, err = 0; if (driver->logging_mode == MEMORY_DEVICE_MODE) { int data_type = 0; if (proc_num == APPS_DATA) { data_type = MEMORY_DEVICE_LOG_TYPE; for (i = 0; i < driver->poolsize_write_struct; i++) if (driver->buf_tbl[i].length == 0) { driver->buf_tbl[i].buf = buf; driver->buf_tbl[i].length = driver->used; #ifdef DIAG_DEBUG printk(KERN_INFO "\n ENQUEUE buf ptr" " and length is %x , %d\n", (unsigned int)(driver->buf_tbl[i].buf), driver->buf_tbl[i].length); #endif break; } #if defined(CONFIG_ARCH_MSM8X60_LTE) } else if (proc_num == MODEM_DATA || proc_num == QDSP_DATA || proc_num == SDIO_DATA) { #else } else if (proc_num == MODEM_DATA || proc_num == QDSP_DATA) { #endif data_type = USERMODE_DIAGFWD; #ifdef DIAG_DEBUG pr_info("%s#%d: Modem Data buf=%p, len=%d\n", __func__, __LINE__, buf, write_ptr->length); #endif #if defined(CONFIG_ARCH_MSM8X60_LTE) if (proc_num == SDIO_DATA) { for (i = 0; i < driver->num_mdmclients; i++) if (driver->mdmclient_map[i].pid == driver->logging_process_id) break; if (i < driver->num_mdmclients) { driver->mdmdata_ready[i] |= data_type; wake_up_interruptible(&driver->mdmwait_q); return err; } else return -EINVAL; } #endif } #if defined(CONFIG_MACH_MECHA) else if (proc_num == SDIO_DATA) { for (i = 0; i < driver->num_mdmclients; i++) if (driver->mdmclient_map[i].pid == driver->logging_process_id) break; if (i <= driver->num_mdmclients) { driver->mdmdata_ready[i] |= MEMORY_DEVICE_LOG_TYPE; wake_up_interruptible(&driver->mdmwait_q); return err; } else return -EINVAL; } #endif for (i = 0; i < driver->num_clients; i++) if (driver->client_map[i].pid == driver->logging_process_id) break; if (i < driver->num_clients) { driver->data_ready[i] |= data_type; wake_up_interruptible(&driver->wait_q); } else return -EINVAL; } else if (driver->logging_mode == NO_LOGGING_MODE) { if (proc_num == MODEM_DATA) { driver->in_busy_1 = 0; driver->in_busy_2 = 0; queue_work(driver->diag_wq, &(driver-> diag_read_smd_work)); } else if (proc_num == QDSP_DATA) { driver->in_busy_qdsp_1 = 0; driver->in_busy_qdsp_2 = 0; queue_work(driver->diag_wq, &(driver-> diag_read_smd_qdsp_work)); } err = -1; } #ifdef CONFIG_DIAG_OVER_USB else if (driver->logging_mode == USB_MODE) { if (proc_num == APPS_DATA) { driver->write_ptr_svc = (struct diag_request *) (diagmem_alloc(driver, sizeof(struct diag_request), POOL_TYPE_WRITE_STRUCT)); if (driver->write_ptr_svc) { driver->write_ptr_svc->length = driver->used; driver->write_ptr_svc->buf = buf; err = usb_diag_write(driver->legacy_ch, driver->write_ptr_svc); } else err = -1; } else if (proc_num == MODEM_DATA) { write_ptr->buf = buf; #ifdef DIAG_DEBUG printk(KERN_INFO "writing data to USB," "pkt length %d\n", write_ptr->length); print_hex_dump(KERN_DEBUG, "Written Packet Data to" " USB: ", DUMP_PREFIX_ADDRESS, 16, 1, buf, write_ptr->length, 1); #endif /* DIAG DEBUG */ driver->diag_smd_count += write_ptr->length; err = usb_diag_write(driver->legacy_ch, write_ptr); } else if (proc_num == QDSP_DATA) { write_ptr->buf = buf; driver->diag_qdsp_count += write_ptr->length; err = usb_diag_write(driver->legacy_ch, write_ptr); } #if defined(CONFIG_ARCH_MSM8X60_LTE)//|| defined(CONFIG_MACH_MECHA) else if (proc_num == SDIO_DATA) { write_ptr->buf = buf; if (diag_ch_sdio) { err = usb_diag_write(driver->legacy_ch, write_ptr); } else { err = usb_diag_write(driver->mdm_ch, write_ptr); } } #endif APPEND_DEBUG('d'); } #endif /* DIAG OVER USB */ return err; }
void diag_process_hdlc(void *data, unsigned len) { struct diag_hdlc_decode_type hdlc; int ret, type = 0; #if HPST_FUN unsigned char *buf_9k = NULL; int path; #endif #ifdef DIAG_DEBUG int i; printk(KERN_INFO "\n HDLC decode function, len of data %d\n", len); #endif hdlc.dest_ptr = driver->hdlc_buf; hdlc.dest_size = USB_MAX_OUT_BUF; hdlc.src_ptr = data; hdlc.src_size = len; hdlc.src_idx = 0; hdlc.dest_idx = 0; hdlc.escaping = 0; ret = diag_hdlc_decode(&hdlc); if (ret) { type = diag_process_apps_pkt(driver->hdlc_buf, hdlc.dest_idx - 3); } else if (driver->debug_flag) { printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC" " errors or partial packet received, packet" " length = %d\n", len); print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1, DUMP_PREFIX_ADDRESS, data, len, 1); driver->debug_flag = 0; } #ifdef DIAG_DEBUG printk(KERN_INFO "\n hdlc.dest_idx = %d \n", hdlc.dest_idx); for (i = 0; i < hdlc.dest_idx; i++) printk(KERN_DEBUG "\t%x", *(((unsigned char *) driver->hdlc_buf)+i)); #endif /* ignore 2 bytes for CRC, one for 7E and send */ if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) { APPEND_DEBUG('g'); #if HPST_FUN /* check for hpst*/ path = checkcmd_modem_hpst(data); switch (path) { case DM7K9K: printk(KERN_INFO "%s:DM7K9K\n", __func__); print_hex_dump(KERN_DEBUG, "HPST:DM Packet Data" " write to radio ", 16, 1, DUMP_PREFIX_ADDRESS, data, 16, 1); smd_write(driver->ch, data, len); buf_9k = kzalloc(len, GFP_KERNEL); memcpy(buf_9k, data, len); msm_sdio_diag_write((void *)buf_9k, len); buf_9k = NULL; break; case DM9KONLY: printk(KERN_INFO "%s:DM9KONLY\n", __func__); print_hex_dump(KERN_DEBUG, "HPST:DM Packet Data" " write to radio ", 16, 1, DUMP_PREFIX_ADDRESS, data, 16, 1); buf_9k = kzalloc(len, GFP_KERNEL); memcpy(buf_9k, data, len); msm_sdio_diag_write((void *)buf_9k, len); buf_9k = NULL; break; case DM7K9KDIFF: printk(KERN_INFO "%s:DM7K9KDIFF", __func__); print_hex_dump(KERN_DEBUG, "HPST:DM Packet Data" " write to radio ", 16, 1, DUMP_PREFIX_ADDRESS, data, 16, 1); if (((*(((uint8_t *)data)+3)) & 0xC0) == 0xC0) { printk(KERN_INFO "%s:DM7K9KDIFF to 9K\n", __func__); buf_9k = kzalloc(len, GFP_KERNEL); memcpy(buf_9k, data, len); msm_sdio_diag_write((void *)buf_9k, len); buf_9k = NULL; } else { printk(KERN_INFO "%s:DM7K9KDIFF to 7K\n", __func__); smd_write(driver->ch, data, len); } break; case DM7KONLY: printk(KERN_INFO "%s:DM7KONLY\n", __func__); print_hex_dump(KERN_DEBUG, "HPST:DM Packet Data" " write to radio ", 16, 1, DUMP_PREFIX_ADDRESS, data, 16, 1); smd_write(driver->ch, data, len); break; case NO_PST: smd_write(driver->ch, data, len); break; case NO_DEF_ID: case NO_DEF_ITEM: default: print_hex_dump(KERN_DEBUG, "HPST:DM Packet Data" " can't write to radio ", 16, 1, DUMP_PREFIX_ADDRESS, data, 16, 1); } #else smd_write(driver->ch, data, len); #endif APPEND_DEBUG('h'); #ifdef DIAG_DEBUG printk(KERN_INFO "writing data to SMD, pkt length %d \n", len); print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16, 1, DUMP_PREFIX_ADDRESS, data, len, 1); #endif } }
static void diag_read_sdio_work_fn(struct work_struct *work) { APPEND_DEBUG('Y'); __diag_sdio_send_req(); }
void __diag_smd_send_req(void) { void *buf = NULL; int *in_busy_ptr = NULL; struct diag_request *write_ptr_modem = NULL; int type; if (!driver->in_busy_1) { buf = driver->usb_buf_in_1; write_ptr_modem = driver->usb_write_ptr_1; in_busy_ptr = &(driver->in_busy_1); } else if (!driver->in_busy_2) { buf = driver->usb_buf_in_2; write_ptr_modem = driver->usb_write_ptr_2; in_busy_ptr = &(driver->in_busy_2); } if (driver->ch && buf) { int r = smd_read_avail(driver->ch); if (r > USB_MAX_IN_BUF) { if (r < MAX_BUF_SIZE) { printk(KERN_ALERT "\n diag: SMD sending in " "packets upto %d bytes", r); buf = krealloc(buf, r, GFP_KERNEL); } else { printk(KERN_ALERT "\n diag: SMD sending in " "packets more than %d bytes", MAX_BUF_SIZE); return; } } if (r > 0) { if (!buf) printk(KERN_INFO "Out of diagmem for a9\n"); else { APPEND_DEBUG('i'); smd_read(driver->ch, buf, r); if (diag7k_debug_mask) { switch (diag7k_debug_mask) { case 1: print_hex_dump(KERN_DEBUG, "Read Packet Data" " from 7K(first 16 bytes)", 16, 1, DUMP_PREFIX_ADDRESS, buf, 16, 1); break; case 2: print_hex_dump(KERN_DEBUG, "Read Packet Data" " from 7K(first 16 bytes)", 16, 1, DUMP_PREFIX_ADDRESS, buf, 16, 1); print_hex_dump(KERN_DEBUG, "Read Packet Data" " from 7K(last 16 bytes) ", 16, 1, DUMP_PREFIX_ADDRESS, buf+r-16, 16, 1); break; default: print_hex_dump(KERN_DEBUG, "Read Packet Data" " from 7K ", 16, 1, DUMP_PREFIX_ADDRESS, buf, r, 1); } } #if EPST_FUN type = checkcmd_modem_epst(buf); if (type) { modem_to_userspace(buf, r, type, 0); return; } #endif APPEND_DEBUG('j'); write_ptr_modem->length = r; *in_busy_ptr = 1; diag_device_write(buf, MODEM_DATA, write_ptr_modem); } } } }
void diag_process_hdlc(void *data, unsigned len) { struct diag_hdlc_decode_type hdlc; int ret, type = 0; #if HPST_FUN unsigned char *buf_9k = NULL; int path; #endif #ifdef DIAG_DEBUG int i; DIAGFWD_INFO("\n HDLC decode function, len of data %d\n", len); #endif hdlc.dest_ptr = driver->hdlc_buf; hdlc.dest_size = USB_MAX_OUT_BUF; hdlc.src_ptr = data; hdlc.src_size = len; hdlc.src_idx = 0; hdlc.dest_idx = 0; hdlc.escaping = 0; ret = diag_hdlc_decode(&hdlc); if (ret) type = diag_process_apps_pkt(driver->hdlc_buf, hdlc.dest_idx - 3); else if (driver->debug_flag) { DIAGFWD_ERR("Packet dropped due to bad HDLC coding/CRC" " errors or partial packet received, packet" " length = %d\n", len); print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1, DUMP_PREFIX_ADDRESS, data, len, 1); driver->debug_flag = 0; } #ifdef CONFIG_DIAG_NO_MODEM if (type == 1) { /* implies this packet is NOT meant for apps */ if (driver->chqdsp) smd_write(driver->chqdsp, driver->hdlc_buf, hdlc.dest_idx - 3); type = 0; } #endif /* NO MODEM present */ #ifdef DIAG_DEBUG printk(KERN_INFO "\n hdlc.dest_idx = %d", hdlc.dest_idx); for (i = 0; i < hdlc.dest_idx; i++) printk(KERN_DEBUG "\t%x", *(((unsigned char *) driver->hdlc_buf)+i)); #endif /* DIAG DEBUG */ /* ignore 2 bytes for CRC, one for 7E and send */ if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) { APPEND_DEBUG('g'); #if defined(CONFIG_ARCH_MSM8X60_LTE) || defined(CONFIG_ARCH_MSM8X60) smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3); #else //defined(CONFIG_MACH_MECHA) smd_write(driver->ch, data, len); #endif if (diag7k_debug_mask) print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16, 1, DUMP_PREFIX_ADDRESS, data, len, 1); APPEND_DEBUG('h'); #ifdef DIAG_DEBUG printk(KERN_INFO "writing data to SMD, pkt length %d \n", len); print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16, 1, DUMP_PREFIX_ADDRESS, data, len, 1); #endif /* DIAG DEBUG */ } }
void __diag_smd_qdsp_send_req(void) { void *buf = NULL; int *in_busy_qdsp_ptr = NULL; struct diag_request *write_ptr_qdsp = NULL; #if DIAG_XPST int type; #endif if (!driver->in_busy_qdsp_1) { buf = driver->buf_in_qdsp_1; write_ptr_qdsp = driver->write_ptr_qdsp_1; in_busy_qdsp_ptr = &(driver->in_busy_qdsp_1); } else if (!driver->in_busy_qdsp_2) { buf = driver->buf_in_qdsp_2; write_ptr_qdsp = driver->write_ptr_qdsp_2; in_busy_qdsp_ptr = &(driver->in_busy_qdsp_2); } if (driver->chqdsp && buf) { int r = smd_read_avail(driver->chqdsp); if (r > IN_BUF_SIZE) { if (r < MAX_IN_BUF_SIZE) { DIAGFWD_INFO("\n diag: SMD sending in " "packets upto %d bytes", r); buf = krealloc(buf, r, GFP_KERNEL); } else { DIAGFWD_ERR("\n diag: SMD sending in " "packets more than %d bytes", MAX_IN_BUF_SIZE); return; } } if (r > 0) { if (!buf) DIAGFWD_INFO("Out of diagmem for QDSP\n"); else { APPEND_DEBUG('i'); smd_read(driver->chqdsp, buf, r); if (diag7k_debug_mask) { switch (diag7k_debug_mask) { case 1: print_hex_dump(KERN_DEBUG, "Read Packet Data" " from qdsp(first 16 bytes)", 16, 1, DUMP_PREFIX_ADDRESS, buf, 16, 1); break; case 2: print_hex_dump(KERN_DEBUG, "Read Packet Data" " from qdsp(first 16 bytes)", 16, 1, DUMP_PREFIX_ADDRESS, buf, 16, 1); print_hex_dump(KERN_DEBUG, "Read Packet Data" " from qdsp(last 16 bytes) ", 16, 1, DUMP_PREFIX_ADDRESS, buf+r-16, 16, 1); break; default: print_hex_dump(KERN_DEBUG, "Read Packet Data" " from qdsp ", 16, 1, DUMP_PREFIX_ADDRESS, buf, r, 1); } } #if DIAG_XPST type = checkcmd_modem_epst(buf); if (type) { modem_to_userspace(buf, r, type, 0); return; } #endif APPEND_DEBUG('j'); write_ptr_qdsp->length = r; *in_busy_qdsp_ptr = 1; diag_device_write(buf, QDSP_DATA, write_ptr_qdsp); } } } }
int diag_device_write(void *buf, int data_type, struct diag_request *write_ptr) { int i, err = 0, index; index = 0; if (driver->logging_mode == MEMORY_DEVICE_MODE) { int hsic_updated = 0; if (data_type == APPS_DATA) { for (i = 0; i < driver->poolsize_write_struct; i++) if (driver->buf_tbl[i].length == 0) { driver->buf_tbl[i].buf = buf; driver->buf_tbl[i].length = driver->used; #ifdef DIAG_DEBUG pr_debug("diag: ENQUEUE buf ptr" " and length is %x , %d\n", (unsigned int)(driver->buf_ tbl[i].buf), driver->buf_tbl[i].length); #endif break; } } #ifdef CONFIG_DIAGFWD_BRIDGE_CODE else if (data_type == HSIC_DATA || data_type == HSIC_2_DATA) { unsigned long flags; int foundIndex = -1; hsic_updated = 1; index = data_type - HSIC_DATA; spin_lock_irqsave(&diag_hsic[index].hsic_spinlock, flags); for (i = 0; i < diag_hsic[index].poolsize_hsic_write; i++) { if (diag_hsic[index].hsic_buf_tbl[i].length == 0) { diag_hsic[index].hsic_buf_tbl[i].buf = buf; diag_hsic[index].hsic_buf_tbl[i].length = diag_bridge[index].write_len; diag_hsic[index]. num_hsic_buf_tbl_entries++; foundIndex = i; break; } } spin_unlock_irqrestore(&diag_hsic[index].hsic_spinlock, flags); if (foundIndex == -1) err = -1; else pr_debug("diag: ENQUEUE HSIC buf ptr and length is %x , %d, ch %d\n", (unsigned int)buf, diag_bridge[index].write_len, index); } #endif for (i = 0; i < driver->num_clients; i++) if (driver->client_map[i].pid == driver->logging_process_id) break; if (i < driver->num_clients) { diag_mem_dev_mode_ready_update(i, hsic_updated); pr_debug("diag: wake up logging process\n"); wake_up_interruptible(&driver->wait_q); } else return -EINVAL; } else if (driver->logging_mode == NO_LOGGING_MODE) { if ((data_type >= 0) && (data_type < NUM_SMD_DATA_CHANNELS)) { driver->smd_data[data_type].in_busy_1 = 0; driver->smd_data[data_type].in_busy_2 = 0; queue_work(driver->diag_wq, &(driver->smd_data[data_type]. diag_read_smd_work)); } #ifdef CONFIG_DIAG_SDIO_PIPE else if (data_type == SDIO_DATA) { driver->in_busy_sdio = 0; queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work)); } #endif #ifdef CONFIG_DIAGFWD_BRIDGE_CODE else if (data_type == HSIC_DATA || data_type == HSIC_2_DATA) { index = data_type - HSIC_DATA; if (diag_hsic[index].hsic_ch) queue_work(diag_bridge[index].wq, &(diag_hsic[index]. diag_read_hsic_work)); } #endif err = -1; } #ifdef CONFIG_DIAG_OVER_USB else if (driver->logging_mode == USB_MODE) { if (data_type == APPS_DATA) { driver->write_ptr_svc = (struct diag_request *) (diagmem_alloc(driver, sizeof(struct diag_request), POOL_TYPE_WRITE_STRUCT)); if (driver->write_ptr_svc) { driver->write_ptr_svc->length = driver->used; driver->write_ptr_svc->buf = buf; err = usb_diag_write(driver->legacy_ch, driver->write_ptr_svc); } else err = -1; } else if ((data_type >= 0) && (data_type < NUM_SMD_DATA_CHANNELS)) { write_ptr->buf = buf; #ifdef DIAG_DEBUG printk(KERN_INFO "writing data to USB," "pkt length %d\n", write_ptr->length); print_hex_dump(KERN_DEBUG, "Written Packet Data to" " USB: ", 16, 1, DUMP_PREFIX_ADDRESS, buf, write_ptr->length, 1); #endif /* DIAG DEBUG */ err = usb_diag_write(driver->legacy_ch, write_ptr); } #ifdef CONFIG_DIAG_SDIO_PIPE else if (data_type == SDIO_DATA) { if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) { write_ptr->buf = buf; err = usb_diag_write(driver->mdm_ch, write_ptr); } else pr_err("diag: Incorrect sdio data " "while USB write\n"); } #endif #ifdef CONFIG_DIAGFWD_BRIDGE_CODE else if (data_type == HSIC_DATA || data_type == HSIC_2_DATA) { index = data_type - HSIC_DATA; if (diag_hsic[index].hsic_device_enabled) { struct diag_request *write_ptr_mdm; write_ptr_mdm = (struct diag_request *) diagmem_alloc(driver, sizeof(struct diag_request), index + POOL_TYPE_HSIC_WRITE); if (write_ptr_mdm) { write_ptr_mdm->buf = buf; write_ptr_mdm->length = diag_bridge[index].write_len; write_ptr_mdm->context = (void *)index; err = usb_diag_write( diag_bridge[index].ch, write_ptr_mdm); /* Return to the pool immediately */ if (err) { diagmem_free(driver, write_ptr_mdm, index + POOL_TYPE_HSIC_WRITE); pr_err_ratelimited("diag: HSIC write failure, err: %d, ch %d\n", err, index); } } else { pr_err("diag: allocate write fail\n"); err = -1; } } else { pr_err("diag: Incorrect HSIC data " "while USB write\n"); err = -1; } } else if (data_type == SMUX_DATA) { write_ptr->buf = buf; write_ptr->context = (void *)SMUX; pr_debug("diag: writing SMUX data\n"); err = usb_diag_write(diag_bridge[SMUX].ch, write_ptr); } #endif APPEND_DEBUG('d'); } #endif /* DIAG OVER USB */ return err; }
void diag_process_hdlc(void *data, unsigned len) { struct diag_hdlc_decode_type hdlc; int ret, type = 0; pr_debug("diag: HDLC decode fn, len of data %d\n", len); hdlc.dest_ptr = driver->hdlc_buf; hdlc.dest_size = USB_MAX_OUT_BUF; hdlc.src_ptr = data; hdlc.src_size = len; hdlc.src_idx = 0; hdlc.dest_idx = 0; hdlc.escaping = 0; ret = diag_hdlc_decode(&hdlc); if (hdlc.dest_idx < 3) { pr_err("diag: Integer underflow in hdlc processing\n"); return; } if (ret) { type = diag_process_apps_pkt(driver->hdlc_buf, hdlc.dest_idx - 3); if (type < 0) return; } else if (driver->debug_flag) { printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC" " errors or partial packet received, packet" " length = %d\n", len); print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1, DUMP_PREFIX_ADDRESS, data, len, 1); driver->debug_flag = 0; } /* send error responses from APPS for Central Routing */ if (type == 1 && chk_apps_only()) { diag_send_error_rsp(hdlc.dest_idx); type = 0; } /* implies this packet is NOT meant for apps */ if (!(driver->smd_data[MODEM_DATA].ch) && type == 1) { if (chk_apps_only()) { diag_send_error_rsp(hdlc.dest_idx); } else { /* APQ 8060, Let Q6 respond */ if (driver->smd_data[LPASS_DATA].ch) smd_write(driver->smd_data[LPASS_DATA].ch, driver->hdlc_buf, hdlc.dest_idx - 3); } type = 0; } #ifdef DIAG_DEBUG pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx); for (i = 0; i < hdlc.dest_idx; i++) printk(KERN_DEBUG "\t%x", *(((unsigned char *) driver->hdlc_buf)+i)); #endif /* DIAG DEBUG */ /* ignore 2 bytes for CRC, one for 7E and send */ if ((driver->smd_data[MODEM_DATA].ch) && (ret) && (type) && (hdlc.dest_idx > 3)) { APPEND_DEBUG('g'); smd_write(driver->smd_data[MODEM_DATA].ch, driver->hdlc_buf, hdlc.dest_idx - 3); APPEND_DEBUG('h'); #ifdef DIAG_DEBUG printk(KERN_INFO "writing data to SMD, pkt length %d\n", len); print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16, 1, DUMP_PREFIX_ADDRESS, data, len, 1); #endif /* DIAG DEBUG */ } }