bool link_pm_set_active(struct usb_link_device *usb_ld) { int ret; struct link_pm_data *pm_data = usb_ld->link_pm_data; struct device *dev; if (has_hub(usb_ld)) { if (pm_data->hub_status != HUB_STATE_ACTIVE) { INIT_COMPLETION(pm_data->hub_active); SET_SLAVE_WAKEUP(usb_ld->pdata, 1); ret = wait_for_completion_timeout(&pm_data->hub_active, msecs_to_jiffies(2000)); if (!ret) { /*timeout*/ pr_err("%s: hub on timeout - retry\n", __func__); SET_SLAVE_WAKEUP(usb_ld->pdata, 0); queue_delayed_work(usb_ld->ld.tx_wq, &usb_ld->ld.tx_delayed_work, 0); return false; } else { pr_err("wait done\n"); usb_make_resume(usb_ld); return true; } } } else { /* TODO do something */ } return true; }
static int start_ipc(struct link_device *ld, struct io_device *iod) { struct sk_buff *skb; char data[1] = {'a'}; int err; struct usb_link_device *usb_ld = to_usb_link_device(ld); struct if_usb_devdata *pipe_data = &usb_ld->devdata[IF_USB_FMT_EP]; if (has_hub(usb_ld) && usb_ld->link_pm_data->hub_handshake_done) { mif_err("Already send start ipc, skip start ipc\n"); err = 0; goto exit; } if (!usb_ld->if_usb_connected) { mif_err("HSIC/USB not connected, skip start ipc\n"); err = -ENODEV; goto exit; } if (has_hub(usb_ld) && usb_ld->if_usb_initstates == INIT_IPC_START_DONE) { mif_debug("Already IPC started\n"); err = 0; goto exit; } mif_info("send 'a'\n"); skb = alloc_skb(16, GFP_ATOMIC); if (unlikely(!skb)) return -ENOMEM; memcpy(skb_put(skb, 1), data, 1); skbpriv(skb)->iod = iod; skbpriv(skb)->ld = &usb_ld->ld; err = usb_tx_urb_with_skb(usb_ld, skb, pipe_data); if (err < 0) { mif_err("usb_tx_urb fail\n"); goto exit; } usb_ld->link_pm_data->hub_handshake_done = true; usb_ld->if_usb_initstates = INIT_IPC_START_DONE; exit: return err; }
/***********************************************************************//** * @brief Print VO client information * * @param[in] chatter Chattiness (defaults to NORMAL). * @return String containing VO client information ***************************************************************************/ std::string GVOClient::print(const GChatter& chatter) const { // Initialise result string std::string result; // Continue only if chatter is not silent if (chatter != SILENT) { // Append header result.append("=== GVOClient ==="); // Append client information result.append("\n"+gammalib::parformat("Name")+m_name); // Append Hub information if (has_hub()) { result.append("\n"+gammalib::parformat("Hub key")+m_secret); result.append("\n"+gammalib::parformat("Hub URL")+m_hub_url); result.append("\n"+gammalib::parformat("Hub host")+m_hub_host); result.append("\n"+gammalib::parformat("Hub port")+m_hub_port); result.append("\n"+gammalib::parformat("Hub path")+m_hub_path); result.append("\n"+gammalib::parformat("SAMP protocol version")); result.append(m_version); result.append("\n"+gammalib::parformat("Hub connection")); if (is_connected()) { if (!m_client_key.empty()) { result.append("registered as \""+m_client_id); result.append("\" on Hub \""+m_hub_id); result.append("\"."); } else { result.append("established."); } } else { result.append("no"); } } else { result.append("\n"+gammalib::parformat("Hub key")); result.append("No Hub has been found"); } } // endif: chatter was not silent // Return result return result; }
/***********************************************************************//** * @brief Unregister client from VO Hub * * Disconnects the VO client from the VO Hub. The client is unregistered. ***************************************************************************/ void GVOClient::disconnect(void) { // Continue only if we have a Hub if (has_hub()) { // Unregister from Hub unregister_from_hub(); // Close socket if (m_socket != -1) { close(m_socket); m_socket = -1; } } // endif: we had a Hub // Return return; }
/***********************************************************************//** * @brief Register client at VO Hub * * Registers a client at the VO Hub. The method will search for a VO Hub, * launch it's own VO Hub if no Hub was found, and the register the client * at the Hub, including sending of metadata. ***************************************************************************/ void GVOClient::connect(void) { // Require a Hub require_hub(); // Continue only if we have a Hub if (has_hub()) { // Register to Hub register_to_hub(); // Send meta data send_metadata(); } // endif: we had a Hub // Return return; }
bool link_pm_is_connected(struct usb_link_device *usb_ld) { if (has_hub(usb_ld)) { if (usb_ld->link_pm_data->hub_init_lock) return false; if (usb_ld->link_pm_data->hub_status != HUB_STATE_ACTIVE) { schedule_delayed_work( &usb_ld->link_pm_data->link_pm_hub, 0); return false; } } if (!usb_ld->if_usb_connected) { mif_err("mif: if not connected\n"); return false; } return true; }
static void if_usb_force_disconnect(struct work_struct *work) { struct usb_link_device *usb_ld = container_of(work, struct usb_link_device, disconnect_work); struct usb_device *udev = usb_ld->usbdev; /* if already disconnected before run this workqueue */ if (!udev || !(&udev->dev) || !usb_ld->if_usb_connected) return; /* disconnect udev's parent if usb hub used */ if (has_hub(usb_ld)) udev = udev->parent; pm_runtime_get_sync(&udev->dev); if (udev->state != USB_STATE_NOTATTACHED) { usb_force_disconnect(udev); mif_info("force disconnect\n"); } pm_runtime_put_autosuspend(&udev->dev); }
bool link_pm_is_connected(struct usb_link_device *usb_ld) { if (has_hub(usb_ld)) { struct link_pm_data *pm_data = usb_ld->link_pm_data; if (pm_data->hub_init_lock) return false; if (pm_data->hub_status == HUB_STATE_OFF) { if (pm_data->hub_work_running == false) start_hub_work(pm_data, 0); return false; } } if (!usb_ld->if_usb_connected) { mif_err("mif: if not connected\n"); return false; } return true; }
static void if_usb_disconnect(struct usb_interface *intf) { struct usb_link_device *usb_ld = usb_get_intfdata(intf); struct usb_device *usbdev = usb_ld->usbdev; struct link_pm_data *pm_data = usb_ld->link_pm_data; int dev_id = intf->altsetting->desc.bInterfaceNumber; struct if_usb_devdata *pipe_data = &usb_ld->devdata[dev_id]; usb_set_intfdata(intf, NULL); pipe_data->disconnected = 1; smp_wmb(); wake_up(&usb_ld->l2_wait); usb_ld->if_usb_connected = 0; usb_ld->flow_suspend = 1; dev_dbg(&usbdev->dev, "%s\n", __func__); usb_ld->dev_count--; usb_driver_release_interface(&if_usb_driver, pipe_data->data_intf); usb_kill_anchored_urbs(&pipe_data->reading); usb_free_urbs(usb_ld, pipe_data); if (usb_ld->dev_count == 0) { cancel_delayed_work_sync(&usb_ld->runtime_pm_work); cancel_delayed_work_sync(&usb_ld->post_resume_work); cancel_delayed_work_sync(&usb_ld->ld.tx_delayed_work); usb_put_dev(usbdev); usb_ld->usbdev = NULL; if (!has_hub(usb_ld)) { if (pm_data->root_hub) pm_runtime_forbid(pm_data->root_hub); schedule_delayed_work(&usb_ld->wait_enumeration, WAIT_ENUMURATION_TIMEOUT_JIFFIES); } } }
/***********************************************************************//** * @brief Find VO Hub * * @return True if VO Hub has been found, false otherwise. * * Search a valid VO Hub and retrieve all mandatory token for this Hub. * The mandatory tokens are * * samp.secret Opaque text string required for Hub registration * samp.hub.xmlrpc.url XML-RPC endpoint for communication * samp.profile.version Version of SAMP profile * * Implements IVOA standard REC-SAMP-1.3-20120411. ***************************************************************************/ bool GVOClient::find_hub(void) { // Allocate line buffer const int n = 1000; char line[n]; // Initialise find flag to false bool found = false; // Get lockfile URL std::string lockurl = get_hub_lockfile(); // Continue only if a URL has been found if (!lockurl.empty()) { // If we have a file:// prefix then strip it now. This is a kluge // and should be remplaced by a method that allows opening any kind // of URL if (lockurl.compare(0, 7, "file://") == 0) { lockurl = lockurl.substr(7, std::string::npos); } // Open SAMP lockfile. Continue only if opening was successful FILE* fptr = fopen(lockurl.c_str(), "r"); if (fptr != NULL) { // Parse lockfile and search for mandatory tokens while (fgets(line, n, fptr) != NULL) { // Convert line to C++ string std::string cline = std::string(line); // Check for secret key if (cline.compare(0, 12, "samp.secret=") == 0) { m_secret = gammalib::strip_chars(cline.substr(12, std::string::npos), "\r\n"); } // Check for Hub URL else if (cline.compare(0, 20, "samp.hub.xmlrpc.url=") == 0) { m_hub_url = gammalib::strip_chars(cline.substr(20, std::string::npos), "\r\n"); } // Check for profile version else if (cline.compare(0, 21, "samp.profile.version=") == 0) { m_version = gammalib::strip_chars(cline.substr(21, std::string::npos), "\r\n"); } } // Close SAMP lockfile fclose(fptr); // Extract host, port and path from Hub URL if (m_hub_url.compare(0, 7, "http://") == 0) { size_t length; size_t start = 7; size_t stop = m_hub_url.find(":", start); size_t end = std::string::npos; if (stop != std::string::npos) { length = stop - start; } else { length = std::string::npos; } m_hub_host = m_hub_url.substr(start, length); if (stop != std::string::npos) { stop++; end = m_hub_url.find("/", stop); if (end != std::string::npos) { length = end - stop; } else { length = std::string::npos; } m_hub_port = m_hub_url.substr(stop, length); } if (end != std::string::npos) { end++; length = m_hub_url.length() - end; m_hub_path = m_hub_url.substr(end, length); } } // Check for existence of mandatory tokens found = has_hub(); } // endif: SAMP lockfile opened } // endif: URL has been found // Return find flag return found; }
static int __devinit if_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_host_interface *data_desc; struct usb_link_device *usb_ld = (struct usb_link_device *)id->driver_info; struct link_device *ld = &usb_ld->ld; struct usb_interface *data_intf; struct usb_device *usbdev = interface_to_usbdev(intf); struct device *dev, *ehci_dev, *root_hub; struct if_usb_devdata *pipe; struct urb *urb; int i; int j; int dev_id; int err; /* To detect usb device order probed */ dev_id = intf->cur_altsetting->desc.bInterfaceNumber; if (dev_id >= IF_USB_DEVNUM_MAX) { dev_err(&intf->dev, "Device id %d cannot support\n", dev_id); return -EINVAL; } if (!usb_ld) { dev_err(&intf->dev, "if_usb device doesn't be allocated\n"); err = ENOMEM; goto out; } mif_info("probe dev_id=%d usb_device_id(0x%p), usb_ld (0x%p)\n", dev_id, id, usb_ld); usb_ld->usbdev = usbdev; usb_get_dev(usbdev); for (i = 0; i < IF_USB_DEVNUM_MAX; i++) { data_intf = usb_ifnum_to_if(usbdev, i); /* remap endpoint of RAW to no.1 for LTE modem */ if (i == 0) pipe = &usb_ld->devdata[1]; else if (i == 1) pipe = &usb_ld->devdata[0]; else pipe = &usb_ld->devdata[i]; pipe->disconnected = 0; pipe->data_intf = data_intf; data_desc = data_intf->cur_altsetting; /* Endpoints */ if (usb_pipein(data_desc->endpoint[0].desc.bEndpointAddress)) { pipe->rx_pipe = usb_rcvbulkpipe(usbdev, data_desc->endpoint[0].desc.bEndpointAddress); pipe->tx_pipe = usb_sndbulkpipe(usbdev, data_desc->endpoint[1].desc.bEndpointAddress); pipe->rx_buf_size = 1024*4; } else { pipe->rx_pipe = usb_rcvbulkpipe(usbdev, data_desc->endpoint[1].desc.bEndpointAddress); pipe->tx_pipe = usb_sndbulkpipe(usbdev, data_desc->endpoint[0].desc.bEndpointAddress); pipe->rx_buf_size = 1024*4; } if (i == 0) { dev_info(&usbdev->dev, "USB IF USB device found\n"); } else { err = usb_driver_claim_interface(&if_usb_driver, data_intf, usb_ld); if (err < 0) { mif_err("failed to cliam usb interface\n"); goto out; } } usb_set_intfdata(data_intf, usb_ld); usb_ld->dev_count++; pm_suspend_ignore_children(&data_intf->dev, true); for (j = 0; j < URB_COUNT; j++) { urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { mif_err("alloc urb fail\n"); err = -ENOMEM; goto out2; } urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; urb->transfer_buffer = usb_alloc_coherent(usbdev, pipe->rx_buf_size, GFP_KERNEL, &urb->transfer_dma); if (!urb->transfer_buffer) { mif_err( "Failed to allocate transfer buffer\n"); usb_free_urb(urb); err = -ENOMEM; goto out2; } usb_fill_bulk_urb(urb, usbdev, pipe->rx_pipe, urb->transfer_buffer, pipe->rx_buf_size, usb_rx_complete, pipe); usb_anchor_urb(urb, &pipe->urbs); } } /* temporary call reset_resume */ atomic_set(&usb_ld->suspend_count, 1); if_usb_reset_resume(data_intf); atomic_set(&usb_ld->suspend_count, 0); SET_HOST_ACTIVE(usb_ld->pdata, 1); usb_ld->host_wake_timeout_flag = 0; if (gpio_get_value(usb_ld->pdata->gpio_phone_active)) { struct link_pm_data *pm_data = usb_ld->link_pm_data; int delay = pm_data->autosuspend_delay_ms ?: DEFAULT_AUTOSUSPEND_DELAY_MS; pm_runtime_set_autosuspend_delay(&usbdev->dev, delay); dev = &usbdev->dev; if (dev->parent) { dev_dbg(&usbdev->dev, "if_usb Runtime PM Start!!\n"); usb_enable_autosuspend(usb_ld->usbdev); /* s5p-ehci runtime pm allow - usb phy suspend mode */ root_hub = &usbdev->bus->root_hub->dev; ehci_dev = root_hub->parent; mif_debug("ehci device = %s, %s\n", dev_driver_string(ehci_dev), dev_name(ehci_dev)); pm_runtime_allow(ehci_dev); if (!pm_data->autosuspend) pm_runtime_forbid(dev); if (has_hub(usb_ld)) link_pm_preactive(pm_data); pm_data->root_hub = root_hub; } usb_ld->flow_suspend = 0; /* Queue work if skbs were pending before a disconnect/probe */ if (ld->sk_fmt_tx_q.qlen || ld->sk_raw_tx_q.qlen) queue_delayed_work(ld->tx_wq, &ld->tx_delayed_work, 0); usb_ld->if_usb_connected = 1; /*USB3503*/ mif_debug("hub active complete\n"); usb_change_modem_state(usb_ld, STATE_ONLINE); } else {