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); } } } }
static void diag_hsic_read_complete_callback(void *ctxt, char *buf, int buf_size, int actual_size) { #if DIAG_XPST && defined(CONFIG_DIAGFWD_BRIDGE_CODE) int type; static int pkt_hdr = DIAG_BODY_OF_NEXT_PKT, first_pkt = 1; #endif int err = -2; if (!driver->hsic_ch) { diagmem_free(driver, buf, POOL_TYPE_HSIC); pr_debug("diag: In %s: driver->hsic_ch == 0, actual_size: %d\n", __func__, actual_size); return; } if ((actual_size > 0) || ((actual_size == 0) && (driver->logging_mode == USB_MODE))) { if (!buf) { pr_err("diag: Out of diagmem for HSIC\n"); } else { DIAGFWD_9K_RAWDATA(buf, "9K", DIAG_DBG_READ); #if DIAG_XPST && defined(CONFIG_DIAGFWD_BRIDGE_CODE) if ((pkt_hdr == DIAG_HEAD_OF_NEXT_PKT || (first_pkt == 1)) && actual_size > 0) { if (unlikely(first_pkt == 1)) first_pkt = 0; type = checkcmd_modem_epst(buf); if (type) { modem_to_userspace(buf, actual_size, type, 1); pkt_hdr = DIAG_HEAD_OF_NEXT_PKT; diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HSIC); return; } pkt_hdr = DIAG_BODY_OF_NEXT_PKT; } if ((actual_size == 1 && *buf == CONTROL_CHAR) || ((actual_size >= 2) && (*(buf+actual_size-1) == CONTROL_CHAR && *(buf+actual_size-2) != ESC_CHAR))) pkt_hdr = DIAG_HEAD_OF_NEXT_PKT; #endif /* * Send data in buf to be written on the * appropriate device, e.g. USB MDM channel */ diag_bridge[HSIC].write_len = actual_size; err = diag_device_write((void *)buf, HSIC_DATA, NULL); if (err) { diagmem_free(driver, buf, POOL_TYPE_HSIC); pr_err_ratelimited("diag: In %s, error calling diag_device_write, err: %d\n", __func__, err); } } } else { diagmem_free(driver, buf, POOL_TYPE_HSIC); pr_debug("diag: In %s: error status: %d\n", __func__, actual_size); } if (err && ((driver->logging_mode == MEMORY_DEVICE_MODE) || (diag_bridge[HSIC].usb_connected && !driver->hsic_suspend))) { queue_work(diag_bridge[HSIC].wq, &driver->diag_read_hsic_work); } }
static int diagchar_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { int err, ret = 0, pkt_type; #ifdef DIAG_DEBUG int length = 0, i; #endif struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 }; struct diag_hdlc_dest_type enc = { NULL, NULL, 0 }; void *buf_copy = NULL; int payload_size; if (((driver->logging_mode == USB_MODE) && (!driver->usb_connected)) || (driver->logging_mode == NO_LOGGING_MODE)) { /*Drop the diag payload */ return -EIO; } /* Get the packet type F3/log/event/Pkt response */ err = copy_from_user((&pkt_type), buf, 4); /*First 4 bytes indicate the type of payload - ignore these */ payload_size = count - 4; if (pkt_type == MEMORY_DEVICE_LOG_TYPE) { if (!mask_request_validate((unsigned char *)buf)) { printk(KERN_ALERT "mask request Invalid ..cannot send to modem \n"); return -EFAULT; } buf = buf + 4; #ifdef DIAG_DEBUG printk(KERN_INFO "\n I got the masks: %d\n", payload_size); for (i = 0; i < payload_size; i++) printk(KERN_DEBUG "\t %x", *(((unsigned char *)buf)+i)); #endif diag_process_hdlc((void *)buf, payload_size); return 0; } buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY); if (!buf_copy) { driver->dropped_count++; return -ENOMEM; } err = copy_from_user(buf_copy, buf + 4, payload_size); if (err) { printk(KERN_INFO "diagchar : copy_from_user failed\n"); ret = -EFAULT; goto fail_free_copy; } #ifdef DIAG_DEBUG printk(KERN_DEBUG "data is -->\n"); for (i = 0; i < payload_size; i++) printk(KERN_DEBUG "\t %x \t", *(((unsigned char *)buf_copy)+i)); #endif send.state = DIAG_STATE_START; send.pkt = buf_copy; send.last = (void *)(buf_copy + payload_size - 1); send.terminate = 1; #ifdef DIAG_DEBUG printk(KERN_INFO "\n Already used bytes in buffer %d, and" " incoming payload size is %d\n", driver->used, payload_size); printk(KERN_DEBUG "hdlc encoded data is -->\n"); for (i = 0; i < payload_size + 8; i++) { printk(KERN_DEBUG "\t %x \t", *(((unsigned char *)buf_hdlc)+i)); if (*(((unsigned char *)buf_hdlc)+i) != 0x7e) length++; } #endif mutex_lock(&driver->diagchar_mutex); if (!buf_hdlc) buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE, POOL_TYPE_HDLC); if (!buf_hdlc) { ret = -ENOMEM; goto fail_free_hdlc; } if (HDLC_OUT_BUF_SIZE - driver->used <= (2*payload_size) + 3) { err = diag_device_write(buf_hdlc, APPS_DATA); if (err) { /*Free the buffer right away if write failed */ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)driver-> usb_write_ptr_svc, POOL_TYPE_USB_STRUCT); ret = -EIO; goto fail_free_hdlc; } buf_hdlc = NULL; #ifdef DIAG_DEBUG printk(KERN_INFO "\n size written is %d\n", driver->used); #endif driver->used = 0; buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE, POOL_TYPE_HDLC); if (!buf_hdlc) { ret = -ENOMEM; goto fail_free_hdlc; } } enc.dest = buf_hdlc + driver->used; enc.dest_last = (void *)(buf_hdlc + driver->used + 2*payload_size + 3); diag_hdlc_encode(&send, &enc); /* This is to check if after HDLC encoding, we are still within the limits of aggregation buffer. If not, we write out the current buffer and start aggregation in a newly allocated buffer */ if ((unsigned int) enc.dest >= (unsigned int)(buf_hdlc + HDLC_OUT_BUF_SIZE)) { err = diag_device_write(buf_hdlc, APPS_DATA); if (err) { /*Free the buffer right away if write failed */ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)driver-> usb_write_ptr_svc, POOL_TYPE_USB_STRUCT); ret = -EIO; goto fail_free_hdlc; } buf_hdlc = NULL; #ifdef DIAG_DEBUG printk(KERN_INFO "\n size written is %d\n", driver->used); #endif driver->used = 0; buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE, POOL_TYPE_HDLC); if (!buf_hdlc) { ret = -ENOMEM; goto fail_free_hdlc; } enc.dest = buf_hdlc + driver->used; enc.dest_last = (void *)(buf_hdlc + driver->used + (2*payload_size) + 3); diag_hdlc_encode(&send, &enc); } driver->used = (uint32_t) enc.dest - (uint32_t) buf_hdlc; if (pkt_type == DATA_TYPE_RESPONSE) { err = diag_device_write(buf_hdlc, APPS_DATA); if (err) { /*Free the buffer right away if write failed */ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)driver-> usb_write_ptr_svc, POOL_TYPE_USB_STRUCT); ret = -EIO; goto fail_free_hdlc; } buf_hdlc = NULL; #ifdef DIAG_DEBUG printk(KERN_INFO "\n size written is %d\n", driver->used); #endif driver->used = 0; } mutex_unlock(&driver->diagchar_mutex); diagmem_free(driver, buf_copy, POOL_TYPE_COPY); if (!timer_in_progress) { timer_in_progress = 1; ret = mod_timer(&drain_timer, jiffies + msecs_to_jiffies(500)); } return 0; fail_free_hdlc: buf_hdlc = NULL; driver->used = 0; diagmem_free(driver, buf_copy, POOL_TYPE_COPY); mutex_unlock(&driver->diagchar_mutex); return ret; fail_free_copy: diagmem_free(driver, buf_copy, POOL_TYPE_COPY); return ret; }
static int diagchar_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { int err, ret = 0, pkt_type; #ifdef DIAG_DEBUG int length = 0, i; #endif struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 }; struct diag_hdlc_dest_type enc = { NULL, NULL, 0 }; void *buf_copy = NULL; unsigned int payload_size; #ifdef CONFIG_DIAG_OVER_USB if (((driver->logging_mode == USB_MODE) && (!driver->usb_connected)) || (driver->logging_mode == NO_LOGGING_MODE)) { /*Drop the diag payload */ return -EIO; } #endif /* DIAG over USB */ /* Get the packet type F3/log/event/Pkt response */ err = copy_from_user((&pkt_type), buf, 4); /* First 4 bytes indicate the type of payload - ignore these */ if (count < 4) { pr_alert("diag: Client sending short data\n"); return -EBADMSG; } payload_size = count - 4; if (payload_size > USER_SPACE_DATA) { pr_err("diag: Dropping packet, packet payload size crosses 8KB limit. Current payload size %d\n", payload_size); driver->dropped_count++; return -EBADMSG; } if (pkt_type == DCI_DATA_TYPE) { err = copy_from_user(driver->user_space_data, buf + 4, payload_size); if (err) { pr_alert("diag: copy failed for DCI data\n"); return DIAG_DCI_SEND_DATA_FAIL; } err = diag_process_dci_client(driver->user_space_data, payload_size); return err; } if (pkt_type == USER_SPACE_LOG_TYPE) { err = copy_from_user(driver->user_space_data, buf + 4, payload_size); /* Check masks for On-Device logging */ if (driver->mask_check) { if (!mask_request_validate(driver->user_space_data)) { pr_alert("diag: mask request Invalid\n"); return -EFAULT; } } buf = buf + 4; #ifdef DIAG_DEBUG pr_debug("diag: user space data %d\n", payload_size); for (i = 0; i < payload_size; i++) pr_debug("\t %x", *((driver->user_space_data)+i)); #endif #ifdef CONFIG_DIAG_SDIO_PIPE /* send masks to 9k too */ if (driver->sdio_ch) { wait_event_interruptible(driver->wait_q, (sdio_write_avail(driver->sdio_ch) >= payload_size)); if (driver->sdio_ch && (payload_size > 0)) { sdio_write(driver->sdio_ch, (void *) (driver->user_space_data), payload_size); } } #endif #ifdef CONFIG_DIAG_BRIDGE_CODE /* send masks to 9k too */ if (driver->hsic_ch && (payload_size > 0)) { /* wait sending mask updates if HSIC ch not ready */ if (driver->in_busy_hsic_write) wait_event_interruptible(driver->wait_q, (driver->in_busy_hsic_write != 1)); driver->in_busy_hsic_write = 1; driver->in_busy_hsic_read_on_device = 0; err = diag_bridge_write(driver->user_space_data, payload_size); if (err) { pr_err("diag: err sending mask to MDM: %d\n", err); /* * If the error is recoverable, then clear * the write flag, so we will resubmit a * write on the next frame. Otherwise, don't * resubmit a write on the next frame. */ if ((-ESHUTDOWN) != err) driver->in_busy_hsic_write = 0; } } #endif /* send masks to 8k now */ diag_process_hdlc((void *)(driver->user_space_data), payload_size); return 0; } if (payload_size > itemsize) { pr_err("diag: Dropping packet, packet payload size crosses" "4KB limit. Current payload size %d\n", payload_size); driver->dropped_count++; return -EBADMSG; } buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY); if (!buf_copy) { driver->dropped_count++; return -ENOMEM; } err = copy_from_user(buf_copy, buf + 4, payload_size); if (err) { printk(KERN_INFO "diagchar : copy_from_user failed\n"); ret = -EFAULT; goto fail_free_copy; } #ifdef DIAG_DEBUG printk(KERN_DEBUG "data is -->\n"); for (i = 0; i < payload_size; i++) printk(KERN_DEBUG "\t %x \t", *(((unsigned char *)buf_copy)+i)); #endif send.state = DIAG_STATE_START; send.pkt = buf_copy; send.last = (void *)(buf_copy + payload_size - 1); send.terminate = 1; #ifdef DIAG_DEBUG pr_debug("diag: Already used bytes in buffer %d, and" " incoming payload size is %d\n", driver->used, payload_size); printk(KERN_DEBUG "hdlc encoded data is -->\n"); for (i = 0; i < payload_size + 8; i++) { printk(KERN_DEBUG "\t %x \t", *(((unsigned char *)buf_hdlc)+i)); if (*(((unsigned char *)buf_hdlc)+i) != 0x7e) length++; } #endif mutex_lock(&driver->diagchar_mutex); if (!buf_hdlc) buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE, POOL_TYPE_HDLC); if (!buf_hdlc) { ret = -ENOMEM; goto fail_free_hdlc; } if (HDLC_OUT_BUF_SIZE - driver->used <= (2*payload_size) + 3) { err = diag_device_write(buf_hdlc, APPS_DATA, NULL); if (err) { /*Free the buffer right away if write failed */ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)driver-> write_ptr_svc, POOL_TYPE_WRITE_STRUCT); ret = -EIO; goto fail_free_hdlc; } buf_hdlc = NULL; driver->used = 0; buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE, POOL_TYPE_HDLC); if (!buf_hdlc) { ret = -ENOMEM; goto fail_free_hdlc; } } enc.dest = buf_hdlc + driver->used; enc.dest_last = (void *)(buf_hdlc + driver->used + 2*payload_size + 3); diag_hdlc_encode(&send, &enc); /* This is to check if after HDLC encoding, we are still within the limits of aggregation buffer. If not, we write out the current buffer and start aggregation in a newly allocated buffer */ if ((unsigned int) enc.dest >= (unsigned int)(buf_hdlc + HDLC_OUT_BUF_SIZE)) { err = diag_device_write(buf_hdlc, APPS_DATA, NULL); if (err) { /*Free the buffer right away if write failed */ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)driver-> write_ptr_svc, POOL_TYPE_WRITE_STRUCT); ret = -EIO; goto fail_free_hdlc; } buf_hdlc = NULL; driver->used = 0; buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE, POOL_TYPE_HDLC); if (!buf_hdlc) { ret = -ENOMEM; goto fail_free_hdlc; } enc.dest = buf_hdlc + driver->used; enc.dest_last = (void *)(buf_hdlc + driver->used + (2*payload_size) + 3); diag_hdlc_encode(&send, &enc); } driver->used = (uint32_t) enc.dest - (uint32_t) buf_hdlc; if (pkt_type == DATA_TYPE_RESPONSE) { err = diag_device_write(buf_hdlc, APPS_DATA, NULL); if (err) { /*Free the buffer right away if write failed */ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)driver-> write_ptr_svc, POOL_TYPE_WRITE_STRUCT); ret = -EIO; goto fail_free_hdlc; } buf_hdlc = NULL; driver->used = 0; } mutex_unlock(&driver->diagchar_mutex); diagmem_free(driver, buf_copy, POOL_TYPE_COPY); if (!timer_in_progress) { timer_in_progress = 1; ret = mod_timer(&drain_timer, jiffies + msecs_to_jiffies(500)); } return 0; fail_free_hdlc: buf_hdlc = NULL; driver->used = 0; diagmem_free(driver, buf_copy, POOL_TYPE_COPY); mutex_unlock(&driver->diagchar_mutex); return ret; fail_free_copy: diagmem_free(driver, buf_copy, POOL_TYPE_COPY); return ret; }
static void diag_hsic_read_complete_callback(void *ctxt, char *buf, int buf_size, int actual_size) { int err = 0; int index = (int)ctxt; static DEFINE_RATELIMIT_STATE(rl, 10*HZ, 1); if (!diag_hsic[index].hsic_ch) { /* * The HSIC channel is closed. Return the buffer to * the pool. Do not send it on. */ diagmem_free(driver, buf, index+POOL_TYPE_MDM); pr_debug("diag: In %s: hsic_ch == 0, actual_size: %d\n", __func__, actual_size); return; } /* * Note that zero length is valid and still needs to be sent to * the USB only when we are logging data to the USB */ if ((actual_size > 0) || ((actual_size == 0) && (driver->logging_mode == USB_MODE))) { if (!buf) { pr_err("diag: Out of diagmem for HSIC\n"); } else { /* * Send data in buf to be written on the * appropriate device, e.g. USB MDM channel */ if (driver->logging_mode == MEMORY_DEVICE_MODE) diag_ws_on_notify(); err = diag_device_write((void *)buf, actual_size, index + HSIC_DATA, index); /* If an error, return buffer to the pool */ if (err) { if (driver->logging_mode == MEMORY_DEVICE_MODE) diag_ws_release(); diagmem_free(driver, buf, index + POOL_TYPE_MDM); if (__ratelimit(&rl)) pr_err("diag: In %s, error calling diag_device_write, err: %d\n", __func__, err); } } } else { /* * The buffer has an error status associated with it. Do not * pass it on. Note that -ENOENT is sent when the diag bridge * is closed. */ diagmem_free(driver, buf, index+POOL_TYPE_MDM); pr_debug("diag: In %s: error status: %d\n", __func__, actual_size); } /* * Actual Size is a negative error value when read complete * fails. Don't queue a read in this case. Doing so will not let * HSIC to goto suspend. * * Queue another read only when the read completes successfully * and Diag is either in Memory device mode or USB is connected. */ if (actual_size >= 0 && (driver->logging_mode == MEMORY_DEVICE_MODE || diag_bridge[index].usb_connected)) { queue_work(diag_bridge[index].wq, &diag_hsic[index].diag_read_hsic_work); } }
static int diagchar_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { int err, ret = 0, pkt_type; #ifdef DIAG_DEBUG int length = 0, i; #endif struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 }; struct diag_hdlc_dest_type enc = { NULL, NULL, 0 }; void *buf_copy = NULL; int payload_size; #if 1// defined(FEATURE_DIAG_LARGE_PACKET) unsigned char is_encoded = 0; void *large_buf_hdlc; #endif #ifdef CONFIG_DIAG_OVER_USB if (((driver->logging_mode == USB_MODE) && (!driver->usb_connected)) || (driver->logging_mode == NO_LOGGING_MODE)) { /*Drop the diag payload */ return -EIO; } #endif /* DIAG over USB */ /* Get the packet type F3/log/event/Pkt response */ err = copy_from_user((&pkt_type), buf, 4); /* First 4 bytes indicate the type of payload - ignore these */ payload_size = count - 4; #if 1 //defined(FEATURE_DIAG_LARGE_PACKET) if(pkt_type == -3) { //-DIAG_DATA_TYPE_RESPONSE => no hdlc encode is_encoded = 1; } else { is_encoded = 0; } if(is_encoded) { large_buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE, POOL_TYPE_HDLC); if (!large_buf_hdlc) { driver->dropped_count++; return -ENOMEM; } err = copy_from_user(large_buf_hdlc, buf + 4, payload_size); if (err) { diagmem_free(driver, large_buf_hdlc, POOL_TYPE_HDLC); printk(KERN_INFO "diagchar : copy_from_user failed \n"); ret = -EFAULT; return ret; } mutex_lock(&driver->diagchar_mutex); driver->write_ptr_svc = (struct diag_request *) (diagmem_alloc(driver, sizeof(struct diag_request), POOL_TYPE_WRITE_STRUCT)); driver->write_ptr_svc->buf = large_buf_hdlc; driver->used = payload_size; driver->write_ptr_svc->length = driver->used; err = usb_diag_write(driver->legacy_ch, driver->write_ptr_svc); if (err) { printk(KERN_INFO "\n size written length[%d] error[%d] \n", driver->used, err); diagmem_free(driver, large_buf_hdlc, POOL_TYPE_HDLC); ret = -EIO; mutex_unlock(&driver->diagchar_mutex); return -EIO; } #ifdef DIAG_DEBUG printk(KERN_INFO "\n LARGE_size written is %d \n", driver->used); #endif driver->used = 0; mutex_unlock(&driver->diagchar_mutex); return 0; } #endif if (pkt_type == USER_SPACE_LOG_TYPE) { err = copy_from_user(driver->user_space_data, buf + 4, payload_size); /* Check masks for On-Device logging */ if (driver->mask_check) { if (!mask_request_validate(driver->user_space_data)) { pr_alert("diag: mask request Invalid\n"); return -EFAULT; } } buf = buf + 4; #ifdef DIAG_DEBUG pr_debug("diag: user space data %d\n", payload_size); for (i = 0; i < payload_size; i++) pr_debug("\t %x", *((driver->user_space_data)+i)); #endif #ifdef CONFIG_DIAG_SDIO_PIPE /* send masks to 9k too */ if (driver->sdio_ch) { wait_event_interruptible(driver->wait_q, (sdio_write_avail(driver->sdio_ch) >= payload_size)); if (driver->sdio_ch && (payload_size > 0)) { sdio_write(driver->sdio_ch, (void *) (driver->user_space_data), payload_size); } } #endif /* send masks to modem now */ diag_process_hdlc((void *)(driver->user_space_data), payload_size); return 0; } if (payload_size > itemsize) { pr_err("diag: Dropping packet, packet payload size crosses" "4KB limit. Current payload size %d\n", payload_size); driver->dropped_count++; return -EBADMSG; } buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY); if (!buf_copy) { driver->dropped_count++; return -ENOMEM; } err = copy_from_user(buf_copy, buf + 4, payload_size); if (err) { printk(KERN_INFO "diagchar : copy_from_user failed\n"); ret = -EFAULT; goto fail_free_copy; } #ifdef DIAG_DEBUG printk(KERN_DEBUG "data is -->\n"); for (i = 0; i < payload_size; i++) printk(KERN_DEBUG "\t %x \t", *(((unsigned char *)buf_copy)+i)); #endif send.state = DIAG_STATE_START; send.pkt = buf_copy; send.last = (void *)(buf_copy + payload_size - 1); send.terminate = 1; #ifdef DIAG_DEBUG pr_debug("diag: Already used bytes in buffer %d, and" " incoming payload size is %d\n", driver->used, payload_size); printk(KERN_DEBUG "hdlc encoded data is -->\n"); for (i = 0; i < payload_size + 8; i++) { printk(KERN_DEBUG "\t %x \t", *(((unsigned char *)buf_hdlc)+i)); if (*(((unsigned char *)buf_hdlc)+i) != 0x7e) length++; } #endif mutex_lock(&driver->diagchar_mutex); if (!buf_hdlc) buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE, POOL_TYPE_HDLC); if (!buf_hdlc) { ret = -ENOMEM; goto fail_free_hdlc; } if (HDLC_OUT_BUF_SIZE - driver->used <= (2*payload_size) + 3) { err = diag_device_write(buf_hdlc, APPS_DATA, NULL); if (err) { /*Free the buffer right away if write failed */ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)driver-> write_ptr_svc, POOL_TYPE_WRITE_STRUCT); ret = -EIO; goto fail_free_hdlc; } buf_hdlc = NULL; driver->used = 0; buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE, POOL_TYPE_HDLC); if (!buf_hdlc) { ret = -ENOMEM; goto fail_free_hdlc; } } enc.dest = buf_hdlc + driver->used; enc.dest_last = (void *)(buf_hdlc + driver->used + 2*payload_size + 3); diag_hdlc_encode(&send, &enc); /* This is to check if after HDLC encoding, we are still within the limits of aggregation buffer. If not, we write out the current buffer and start aggregation in a newly allocated buffer */ if ((unsigned int) enc.dest >= (unsigned int)(buf_hdlc + HDLC_OUT_BUF_SIZE)) { err = diag_device_write(buf_hdlc, APPS_DATA, NULL); if (err) { /*Free the buffer right away if write failed */ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)driver-> write_ptr_svc, POOL_TYPE_WRITE_STRUCT); ret = -EIO; goto fail_free_hdlc; } buf_hdlc = NULL; driver->used = 0; buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE, POOL_TYPE_HDLC); if (!buf_hdlc) { ret = -ENOMEM; goto fail_free_hdlc; } enc.dest = buf_hdlc + driver->used; enc.dest_last = (void *)(buf_hdlc + driver->used + (2*payload_size) + 3); diag_hdlc_encode(&send, &enc); } driver->used = (uint32_t) enc.dest - (uint32_t) buf_hdlc; if (pkt_type == DATA_TYPE_RESPONSE) { err = diag_device_write(buf_hdlc, APPS_DATA, NULL); if (err) { /*Free the buffer right away if write failed */ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)driver-> write_ptr_svc, POOL_TYPE_WRITE_STRUCT); ret = -EIO; goto fail_free_hdlc; } buf_hdlc = NULL; driver->used = 0; } mutex_unlock(&driver->diagchar_mutex); diagmem_free(driver, buf_copy, POOL_TYPE_COPY); if (!timer_in_progress) { timer_in_progress = 1; ret = mod_timer(&drain_timer, jiffies + msecs_to_jiffies(500)); } return 0; fail_free_hdlc: buf_hdlc = NULL; driver->used = 0; diagmem_free(driver, buf_copy, POOL_TYPE_COPY); mutex_unlock(&driver->diagchar_mutex); return ret; fail_free_copy: diagmem_free(driver, buf_copy, POOL_TYPE_COPY); return ret; }
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); } } } }