static int rmnet_ctl_open(struct inode *inode, struct file *file) { int retval = 0; struct rmnet_ctrl_dev *dev = container_of(inode->i_cdev, struct rmnet_ctrl_dev, cdev); if (!dev) return -ENODEV; if (dev->is_opened) goto already_opened; ctrl_open: if (!is_dev_connected(dev)) { dev_dbg(dev->devicep, "%s: Device not connected\n", __func__); return -ENODEV; } /*block open to get first response available from mdm*/ if (dev->mdm_wait_timeout && !dev->resp_available) { retval = wait_event_interruptible_timeout( dev->open_wait_queue, dev->resp_available || !is_dev_connected(dev), msecs_to_jiffies(dev->mdm_wait_timeout * 1000)); if (retval == 0) { dev_err(dev->devicep, "%s: Timeout opening %s\n", __func__, dev->name); return -ETIMEDOUT; } else if (retval < 0) { dev_err(dev->devicep, "%s: Error waiting for %s\n", __func__, dev->name); return retval; } goto ctrl_open; } if (!dev->resp_available) { dev_dbg(dev->devicep, "%s: Connection timedout opening %s\n", __func__, dev->name); return -ETIMEDOUT; } mutex_lock(&dev->dev_lock); dev->is_opened = 1; mutex_unlock(&dev->dev_lock); file->private_data = dev; already_opened: DBG("%s: Open called for %s\n", __func__, dev->name); return 0; }
static int rmnet_ctl_release(struct inode *inode, struct file *file) { struct ctrl_pkt_list_elem *list_elem = NULL; struct rmnet_ctrl_dev *dev; unsigned long flag; dev = file->private_data; if (!dev) return -ENODEV; DBG("%s Called on %s device\n", __func__, dev->name); spin_lock_irqsave(&dev->rx_lock, flag); while (!list_empty(&dev->rx_list)) { list_elem = list_first_entry( &dev->rx_list, struct ctrl_pkt_list_elem, list); list_del(&list_elem->list); kfree(list_elem->cpkt.data); kfree(list_elem); } spin_unlock_irqrestore(&dev->rx_lock, flag); mutex_lock(&dev->dev_lock); dev->is_opened = 0; mutex_unlock(&dev->dev_lock); if (is_dev_connected(dev)) usb_kill_anchored_urbs(&dev->tx_submitted); file->private_data = NULL; return 0; }
static int rmnet_usb_ctrl_write_cmd(struct rmnet_ctrl_dev *dev) { int retval = 0; struct usb_device *udev; if (!is_dev_connected(dev)) return -ENODEV; udev = interface_to_usbdev(dev->intf); retval = usb_autopm_get_interface(dev->intf); if (retval < 0) { dev_err(dev->devicep, "%s: Unable to resume interface: %d\n", __func__, retval); /* * Revisit if (retval == -EPERM) * rmnet_usb_suspend(dev->intf, PMSG_SUSPEND); */ return retval; } dev->set_ctrl_line_state_cnt++; retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), USB_CDC_REQ_SET_CONTROL_LINE_STATE, (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE), dev->cbits_tomdm, dev->intf->cur_altsetting->desc.bInterfaceNumber, NULL, 0, USB_CTRL_SET_TIMEOUT); usb_autopm_put_interface(dev->intf); return retval; }
void rmnet_usb_ctrl_stop_all(void) { int id; for (id = 0; id < NUM_CTRL_CHANNELS; id++) { if (is_dev_connected(ctrl_dev[id])) rmnet_usb_ctrl_stop_rx(ctrl_dev[id]); } }
int rmnet_usb_ctrl_stop_rx(struct rmnet_ctrl_dev *dev) { if (!is_dev_connected(dev)) { dev_dbg(dev->devicep, "%s: Ctrl device disconnected\n", __func__); return -ENODEV; } dev_dbg(dev->devicep, "%s\n", __func__); usb_kill_urb(dev->rcvurb); usb_kill_urb(dev->inturb); return 0; }
static int rmnet_usb_ctrl_write_cmd(struct rmnet_ctrl_dev *dev) { struct usb_device *udev; if (!is_dev_connected(dev)) return -ENODEV; udev = interface_to_usbdev(dev->intf); dev->set_ctrl_line_state_cnt++; return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), USB_CDC_REQ_SET_CONTROL_LINE_STATE, (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE), dev->cbits_tomdm, dev->intf->cur_altsetting->desc.bInterfaceNumber, NULL, 0, USB_CTRL_SET_TIMEOUT); }
static ssize_t rmnet_ctl_write(struct file *file, const char __user * buf, size_t size, loff_t *pos) { int status; void *wbuf; struct rmnet_ctrl_dev *dev = file->private_data; if (!dev) return -ENODEV; if (size <= 0) return -EINVAL; if (!is_dev_connected(dev)) return -ENETRESET; if (!dev->is_opened) return size; if (dev->tx_block) { pr_info("%s: tx blocked by reset, just return\n", __func__); return size; } DBG("%s: Writing %i bytes on %s\n", __func__, size, dev->name); wbuf = kmalloc(size , GFP_KERNEL); if (!wbuf) return -ENOMEM; status = copy_from_user(wbuf , buf, size); if (status) { dev_err(dev->devicep, "%s: Unable to copy data from userspace %d\n", __func__, status); kfree(wbuf); return status; } DUMP_BUFFER("Write: ", size, buf); status = rmnet_usb_ctrl_write(dev, wbuf, size); if (status == size) return size; return status; }
static unsigned int rmnet_ctl_poll(struct file *file, poll_table *wait) { unsigned int mask = 0; struct rmnet_ctrl_dev *dev; dev = file->private_data; if (!dev) return POLLERR; poll_wait(file, &dev->read_wait_queue, wait); if (!is_dev_connected(dev)) { dev_dbg(dev->devicep, "%s: Device not connected\n", __func__); return POLLERR; } if (!list_empty(&dev->rx_list)) mask |= POLLIN | POLLRDNORM; return mask; }
static ssize_t rmnet_ctl_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int retval = 0; int bytes_to_read; struct rmnet_ctrl_dev *dev; struct ctrl_pkt_list_elem *list_elem = NULL; unsigned long flags; char temp[100]; dev = file->private_data; if (!dev) return -ENODEV; DBG("%s: Read from %s\n", __func__, dev->name); ctrl_read: if (!is_dev_connected(dev)) { dev_dbg(dev->devicep, "%s: Device not connected\n", __func__); return -ENETRESET; } spin_lock_irqsave(&dev->rx_lock, flags); if (list_empty(&dev->rx_list)) { spin_unlock_irqrestore(&dev->rx_lock, flags); retval = wait_event_interruptible(dev->read_wait_queue, !list_empty(&dev->rx_list) || !is_dev_connected(dev)); if (retval < 0) return retval; goto ctrl_read; } list_elem = list_first_entry(&dev->rx_list, struct ctrl_pkt_list_elem, list); bytes_to_read = (uint32_t)(list_elem->cpkt.data_size); if (bytes_to_read > count) { spin_unlock_irqrestore(&dev->rx_lock, flags); dev_err(dev->devicep, "%s: Packet size %d > buf size %d\n", __func__, bytes_to_read, count); return -ENOMEM; } spin_unlock_irqrestore(&dev->rx_lock, flags); if (copy_to_user(buf, list_elem->cpkt.data, bytes_to_read)) { dev_err(dev->devicep, "%s: copy_to_user failed for %s\n", __func__, dev->name); return -EFAULT; } spin_lock_irqsave(&dev->rx_lock, flags); list_del(&list_elem->list); spin_unlock_irqrestore(&dev->rx_lock, flags); kfree(list_elem->cpkt.data); kfree(list_elem); DBG("%s: Returning %d bytes to %s\n", __func__, bytes_to_read, dev->name); snprintf(temp, sizeof(temp), "[%lluns]READ :", rd_poll_delta_time); DUMP_BUFFER(temp, bytes_to_read, buf); return bytes_to_read; }
static int rmnet_usb_ctrl_write(struct rmnet_ctrl_dev *dev, char *buf, size_t size) { int result; struct urb *sndurb; struct usb_ctrlrequest *out_ctlreq; struct usb_device *udev; if (!is_dev_connected(dev)) return -ENETRESET; udev = interface_to_usbdev(dev->intf); sndurb = usb_alloc_urb(0, GFP_KERNEL); if (!sndurb) { dev_err(dev->devicep, "Error allocating read urb\n"); return -ENOMEM; } out_ctlreq = kmalloc(sizeof(*out_ctlreq), GFP_KERNEL); if (!out_ctlreq) { usb_free_urb(sndurb); dev_err(dev->devicep, "Error allocating setup packet buffer\n"); return -ENOMEM; } /* CDC Send Encapsulated Request packet */ out_ctlreq->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE); out_ctlreq->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND; out_ctlreq->wValue = 0; out_ctlreq->wIndex = dev->intf->cur_altsetting->desc.bInterfaceNumber; out_ctlreq->wLength = cpu_to_le16(size); usb_fill_control_urb(sndurb, udev, usb_sndctrlpipe(udev, 0), (unsigned char *)out_ctlreq, (void *)buf, size, ctrl_write_callback, dev); result = usb_autopm_get_interface(dev->intf); if (result < 0) { dev_dbg(dev->devicep, "%s: Unable to resume interface: %d\n", __func__, result); /* * Revisit: if (result == -EPERM) * rmnet_usb_suspend(dev->intf, PMSG_SUSPEND); */ usb_free_urb(sndurb); kfree(out_ctlreq); return result; } usb_anchor_urb(sndurb, &dev->tx_submitted); dev->snd_encap_cmd_cnt++; result = usb_submit_urb(sndurb, GFP_KERNEL); if (result < 0) { dev_err(dev->devicep, "%s: Submit URB error %d\n", __func__, result); dev->snd_encap_cmd_cnt--; usb_autopm_put_interface(dev->intf); usb_unanchor_urb(sndurb); usb_free_urb(sndurb); kfree(out_ctlreq); return result; } return size; }
static int rmnet_usb_ctrl_write(struct rmnet_ctrl_dev *dev, char *buf, size_t size) { int result; struct urb *sndurb; struct usb_ctrlrequest *out_ctlreq; struct usb_device *udev; #ifdef HTC_DEBUG_QMI_STUCK struct ctrl_write_context *context; #endif if (!is_dev_connected(dev)) return -ENETRESET; udev = interface_to_usbdev(dev->intf); sndurb = usb_alloc_urb(0, GFP_KERNEL); if (!sndurb) { dev_err(dev->devicep, "Error allocating read urb\n"); return -ENOMEM; } out_ctlreq = kmalloc(sizeof(*out_ctlreq), GFP_KERNEL); if (!out_ctlreq) { usb_free_urb(sndurb); dev_err(dev->devicep, "Error allocating setup packet buffer\n"); return -ENOMEM; } #ifdef HTC_DEBUG_QMI_STUCK context = kmalloc(sizeof(struct ctrl_write_context), GFP_KERNEL); if (!context) { kfree(out_ctlreq); usb_free_urb(sndurb); dev_err(dev->devicep, "Error allocating private data\n"); return -ENOMEM; } context->dev = dev; #endif out_ctlreq->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE); out_ctlreq->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND; out_ctlreq->wValue = 0; out_ctlreq->wIndex = dev->intf->cur_altsetting->desc.bInterfaceNumber; out_ctlreq->wLength = cpu_to_le16(size); usb_fill_control_urb(sndurb, udev, usb_sndctrlpipe(udev, 0), (unsigned char *)out_ctlreq, (void *)buf, size, #ifdef HTC_DEBUG_QMI_STUCK ctrl_write_callback, context); #else ctrl_write_callback, dev); #endif result = usb_autopm_get_interface(dev->intf); if (result < 0) { dev_err(dev->devicep, "%s: Unable to resume interface: %d\n", __func__, result); usb_free_urb(sndurb); kfree(out_ctlreq); #ifdef HTC_DEBUG_QMI_STUCK kfree(context); #endif return result; } #ifdef HTC_LOG_RMNET_USB_CTRL log_rmnet_usb_ctrl_event(dev->intf, "Tx", size); #endif #ifdef HTC_DEBUG_QMI_STUCK init_timer(&context->timer); context->timer.function = rmnet_usb_ctrl_write_timer_expire; context->timer.data = (unsigned long)sndurb; context->start_jiffies = jiffies; mod_timer(&context->timer, jiffies + msecs_to_jiffies(QMI_TX_NO_CB_TIMEOUT)); #endif usb_anchor_urb(sndurb, &dev->tx_submitted); dev->snd_encap_cmd_cnt++; result = usb_submit_urb(sndurb, GFP_KERNEL); if (result < 0) { dev_err(dev->devicep, "%s: Submit URB error %d\n", __func__, result); dev->snd_encap_cmd_cnt--; usb_autopm_put_interface(dev->intf); usb_unanchor_urb(sndurb); usb_free_urb(sndurb); kfree(out_ctlreq); #ifdef HTC_DEBUG_QMI_STUCK del_timer(&context->timer); kfree(context); #endif return result; } return size; }