static void ush_hsic_port_disable(void)
{
	hsic_enable = 0;
	if ((hsic.modem_dev) && (hsic.autosuspend_enable != 0)) {
		dev_dbg(&pci_dev->dev,
			"Disable auto suspend in port disable\n");
		usb_disable_autosuspend(hsic.modem_dev);
		usb_disable_autosuspend(hsic.rh_dev);
		hsic.autosuspend_enable = 0;
	}

	if (hsic.rh_dev) {
		if (hsic.autosuspend_enable != 0) {
			dev_dbg(&pci_dev->dev,
			"Disable auto suspend in port disable\n");
			usb_disable_autosuspend(hsic.rh_dev);
			hsic.autosuspend_enable = 0;
		}
		clear_port_feature(hsic.rh_dev, HSIC_USH_PORT,
				USB_PORT_FEAT_POWER);
		usb_enable_autosuspend(hsic.rh_dev);
		hsic.autosuspend_enable = 1;
	}
	s3_wake_unlock();
}
Example #2
0
static ssize_t
set_level(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{
	struct usb_device *udev = to_usb_device(dev);
	int len = count;
	char *cp;
	int rc = count;

	warn_level();
	cp = memchr(buf, '\n', count);
	if (cp)
		len = cp - buf;

	usb_lock_device(udev);

	if (len == sizeof on_string - 1 &&
			strncmp(buf, on_string, len) == 0)
		usb_disable_autosuspend(udev);

	else if (len == sizeof auto_string - 1 &&
			strncmp(buf, auto_string, len) == 0)
		usb_enable_autosuspend(udev);

	else
		rc = -EINVAL;

	usb_unlock_device(udev);
	return rc;
}
Example #3
0
static int csvt_probe(struct usb_serial *serial, const struct usb_device_id *id)
{
	pr_debug("%s:\n", __func__);

	usb_enable_autosuspend(serial->dev);

	return 0;
}
static ssize_t hsic_autosuspend_enable_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t size)
{
	int retval;
	int org_req;

	if (size > HSIC_ENABLE_SIZE) {
		dev_dbg(dev, "Invalid, size = %d\n", size);
		return -EINVAL;
	}

	if (sscanf(buf, "%d", &org_req) != 1) {
		dev_dbg(dev, "Invalid, value\n");
		return -EINVAL;
	}

	mutex_lock(&hsic.hsic_mutex);
	hsic.autosuspend_enable = org_req;
	if (hsic.modem_dev != NULL) {
		if (hsic.autosuspend_enable == 0) {
			dev_dbg(dev, "Modem dev autosuspend disable\n");
			usb_disable_autosuspend(hsic.modem_dev);
		} else {
			dev_dbg(dev, "Enable auto suspend\n");
			usb_enable_autosuspend(hsic.modem_dev);
			hsic_wakeup_irq_init();
		}
	}
	if (hsic.rh_dev != NULL) {
		if (hsic.autosuspend_enable == 0) {
			dev_dbg(dev, "port autosuspend disable\n");
			usb_disable_autosuspend(hsic.rh_dev);
		} else {
			dev_dbg(dev, "port Enable auto suspend\n");
			usb_enable_autosuspend(hsic.rh_dev);
		}
	}

	mutex_unlock(&hsic.hsic_mutex);
	return size;
}
static int wrigley_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
{
	int status = cdc_bind(dev, intf);

	if (!status) {
		dev->rx_urb_size = WRIGLEY_DOWNLINK_MTU +
						dev->net->hard_header_len;
		device_init_wakeup(&dev->udev->dev, 1);
		usb_enable_autosuspend(interface_to_usbdev(intf));
		oob_wake_register(intf);
		dev->udev->autosuspend_delay = msecs_to_jiffies(1000);
		dev->udev->parent->autosuspend_delay = 0;
	}
	return status;
}
Example #6
0
static void tegra_usbdevice_added(struct usb_device *udev)
{
	const struct usb_device_descriptor *desc = &udev->descriptor;

	if (desc->idVendor == mdata->vid &&
	    desc->idProduct == mdata->pid) {
		pr_debug("%s: Device %s added.\n", udev->product, __func__);

		if (callback && callback->usbnotify)
			callback->usbnotify(udev, true);
		if (mdata->wake_capable)
			device_set_wakeup_enable(&udev->dev, true);
		if (mdata->autosuspend_ready)
			usb_enable_autosuspend(udev);
	}
}
static void baseband_xmm_device_add_handler(struct usb_device *udev)
{
	struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
	const struct usb_device_id *id;

	if (intf == NULL)
		return;

	id = usb_match_id(intf, xmm_pm_ids);

	if (id) {
		pr_debug("persist_enabled: %u\n", udev->persist_enabled);
		pr_debug("Add device %d <%s %s>\n", udev->devnum, udev->manufacturer, udev->product);
		usbdev = udev;
		usb_enable_autosuspend(udev);
		pr_debug("enable autosuspend\n");
	}
}
Example #8
0
static void rmnet_usb_disable_hsic_autosuspend(struct usbnet *usbnet,
						int enable_autosuspend)
{
	struct usb_device *usb_dev = usbnet->udev;
	struct rmnet_ctrl_udev *rmnet_udev =
		(struct rmnet_ctrl_udev *)usbnet->data[1];

	usb_get_dev(usb_dev);
	if (!enable_autosuspend) {
		usb_disable_autosuspend(usb_dev);
		rmnet_udev->autosuspend_disabled = 1;
		rmnet_udev->autosuspend_dis_cnt++;
	} else {
		usb_enable_autosuspend(usb_dev);
		rmnet_udev->autosuspend_disabled = 0;
		rmnet_udev->autosuspend_en_cnt++;
	}
	usb_put_dev(usb_dev);
}
Example #9
0
static int 
usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	int retval =0 ;	
   	PMINI_ADAPTER psAdapter = NULL;
	PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
	struct usb_device      *udev = NULL;

//	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Usbbcm probe!!");
	if((intf == NULL) || (id == NULL))
	{
	//	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "intf or id is NULL");
		return -EINVAL;
	}

	/* Allocate Adapter structure */
	if((psAdapter = kmalloc(sizeof(MINI_ADAPTER), GFP_KERNEL)) == NULL)
	{
		//BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0, "Out of memory");
		return -ENOMEM;
	}
	
	memset(psAdapter, 0, sizeof(MINI_ADAPTER));

    /* Init default driver debug state */

    psAdapter->stDebugState.debug_level = DBG_LVL_CURR;
	psAdapter->stDebugState.type = DBG_TYPE_INITEXIT;
	memset (psAdapter->stDebugState.subtype, 0, sizeof (psAdapter->stDebugState.subtype));

    /* Technically, one can start using BCM_DEBUG_PRINT after this point.
	 * However, realize that by default the Type/Subtype bitmaps are all zero now;
	 * so no prints will actually appear until the TestApp turns on debug paths via 
	 * the ioctl(); so practically speaking, in early init, no logging happens.
	 *
	 * A solution (used below): we explicitly set the bitmaps to 1 for Type=DBG_TYPE_INITEXIT
	 * and ALL subtype's of the same. Now all bcm debug statements get logged, enabling debug
	 * during early init.
	 * Further, we turn this OFF once init_module() completes.
	 */

    psAdapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0xff;
	BCM_SHOW_DEBUG_BITMAP(psAdapter);

	retval = InitAdapter(psAdapter);
	if(retval)
	{
		BCM_DEBUG_PRINT (psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InitAdapter Failed\n");
		AdapterFree(psAdapter);
		return retval;
	}

	/* Allocate interface adapter structure */
	if((psAdapter->pvInterfaceAdapter = 
		kmalloc(sizeof(S_INTERFACE_ADAPTER), GFP_KERNEL)) == NULL)
	{
		BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0, "Out of memory");
		AdapterFree (psAdapter);
		return -ENOMEM;
	}
	memset(psAdapter->pvInterfaceAdapter, 0, sizeof(S_INTERFACE_ADAPTER));

	psIntfAdapter = InterfaceAdapterGet(psAdapter);
	psIntfAdapter->psAdapter = psAdapter;
	
	/* Store usb interface in Interface Adapter */
	psIntfAdapter->interface = intf;
	usb_set_intfdata(intf, psIntfAdapter);

	BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "psIntfAdapter 0x%x",(unsigned int)psIntfAdapter);
	retval = InterfaceAdapterInit(psIntfAdapter);
	if(retval)
	{	
		/* If the Firmware/Cfg File is not present
 		 * then return success, let the application
 		 * download the files. 
 		 */
		if(-ENOENT == retval){
			BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "File Not Found, Use App to Download\n");
			return STATUS_SUCCESS;
		}
		BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InterfaceAdapterInit Failed \n");
		usb_set_intfdata(intf, NULL);	
		udev = interface_to_usbdev (intf);
		usb_put_dev(udev);
		if(psAdapter->bUsbClassDriverRegistered == TRUE)
				usb_deregister_dev (intf, &usbbcm_class);
		InterfaceAdapterFree(psIntfAdapter);
		return retval ;
	}
	if(psAdapter->chip_id > T3)
	{
		uint32_t uiNackZeroLengthInt=4;
		if(wrmalt(psAdapter, DISABLE_USB_ZERO_LEN_INT, &uiNackZeroLengthInt, sizeof(uiNackZeroLengthInt)))
		{
			return -EIO;;
		}
	}

	udev = interface_to_usbdev (intf);
	/* Check whether the USB-Device Supports remote Wake-Up */
	if(USB_CONFIG_ATT_WAKEUP & udev->actconfig->desc.bmAttributes) 
	{
		/* If Suspend then only support dynamic suspend */
		if(psAdapter->bDoSuspend) 
		{
			udev->autosuspend_delay = 0;
			intf->needs_remote_wakeup = 1;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
			udev->autosuspend_disabled = 0;
#else
			usb_enable_autosuspend(udev);
#endif
			device_init_wakeup(&intf->dev,1);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
			usb_autopm_disable(intf);
#endif
			INIT_WORK(&psIntfAdapter->usbSuspendWork, putUsbSuspend);
			BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Enabling USB Auto-Suspend\n");
		}
		else
		{ 
			intf->needs_remote_wakeup = 0;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
			udev->autosuspend_disabled = 1;
#else
			usb_disable_autosuspend(udev);
#endif
		}
	}

    psAdapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0x0;
    return retval;
}
Example #10
0
static int
ksb_usb_probe(struct usb_interface *ifc, const struct usb_device_id *id)
{
	__u8				ifc_num;
	struct usb_host_interface	*ifc_desc;
	struct usb_endpoint_descriptor	*ep_desc;
	int				i;
	struct ks_bridge		*ksb;
	unsigned long			flags;
	struct data_pkt			*pkt;

	ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;

	switch (id->idProduct) {
	case 0x9008:
		if (ifc_num != 0)
			return -ENODEV;
		ksb = __ksb[BOOT_BRIDGE_INDEX];
		break;
	case 0x9048:
	case 0x904C:
	case 0x9075:
		if (ifc_num != 2)
			return -ENODEV;
		ksb = __ksb[EFS_BRIDGE_INDEX];
		break;
	default:
		return -ENODEV;
	}

	if (!ksb) {
		pr_err("ksb is not initialized");
		return -ENODEV;
	}

	ksb->udev = usb_get_dev(interface_to_usbdev(ifc));
	ksb->ifc = ifc;
	ifc_desc = ifc->cur_altsetting;

	for (i = 0; i < ifc_desc->desc.bNumEndpoints; i++) {
		ep_desc = &ifc_desc->endpoint[i].desc;

		if (!ksb->in_epAddr && usb_endpoint_is_bulk_in(ep_desc))
			ksb->in_epAddr = ep_desc->bEndpointAddress;

		if (!ksb->out_epAddr && usb_endpoint_is_bulk_out(ep_desc))
			ksb->out_epAddr = ep_desc->bEndpointAddress;
	}

	if (!(ksb->in_epAddr && ksb->out_epAddr)) {
		pr_err("could not find bulk in and bulk out endpoints");
		usb_put_dev(ksb->udev);
		ksb->ifc = NULL;
		return -ENODEV;
	}

	ksb->in_pipe = usb_rcvbulkpipe(ksb->udev, ksb->in_epAddr);
	ksb->out_pipe = usb_sndbulkpipe(ksb->udev, ksb->out_epAddr);

	usb_set_intfdata(ifc, ksb);
	set_bit(USB_DEV_CONNECTED, &ksb->flags);
	atomic_set(&ksb->tx_pending_cnt, 0);
	atomic_set(&ksb->rx_pending_cnt, 0);

	dbg_log_event(ksb, "PID-ATT", id->idProduct, 0);

	/*free up stale buffers if any from previous disconnect*/
	spin_lock_irqsave(&ksb->lock, flags);
	while (!list_empty(&ksb->to_ks_list)) {
		pkt = list_first_entry(&ksb->to_ks_list,
				struct data_pkt, list);
		list_del_init(&pkt->list);
		ksb_free_data_pkt(pkt);
	}
	while (!list_empty(&ksb->to_mdm_list)) {
		pkt = list_first_entry(&ksb->to_mdm_list,
				struct data_pkt, list);
		list_del_init(&pkt->list);
		ksb_free_data_pkt(pkt);
	}
	spin_unlock_irqrestore(&ksb->lock, flags);

	ksb->fs_dev = (struct miscdevice *)id->driver_info;
	misc_register(ksb->fs_dev);

	if (device_can_wakeup(&ksb->udev->dev)) {
		ifc->needs_remote_wakeup = 1;
		usb_enable_autosuspend(ksb->udev);
	}
        atomic_set(&ksb->pmlock_cnt, 0);

	pr_info("usb dev connected");

	return 0;
}
Example #11
0
static int btusb_probe(struct usb_interface *intf,
				const struct usb_device_id *id)
{
	struct usb_endpoint_descriptor *ep_desc;
	struct btusb_data *data;
	struct hci_dev *hdev;
	int i, version, err;

	BT_DBG("intf %p id %p", intf, id);

	/* interface numbers are hardcoded in the spec */
	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
		return -ENODEV;

	if (!id->driver_info) {
		const struct usb_device_id *match;
		match = usb_match_id(intf, blacklist_table);
		if (match)
			id = match;
	}

	if (id->driver_info == BTUSB_IGNORE)
		return -ENODEV;

	if (ignore_dga && id->driver_info & BTUSB_DIGIANSWER)
		return -ENODEV;

	if (ignore_csr && id->driver_info & BTUSB_CSR)
		return -ENODEV;

	if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)
		return -ENODEV;

	if (id->driver_info & BTUSB_ATH3012) {
		struct usb_device *udev = interface_to_usbdev(intf);

		version = get_rome_version(udev);
		BT_INFO("Rome Version: 0x%x",  version);
		/* Old firmware would otherwise let ath3k driver load
		 * patch and sysconfig files */
		if (version)
			rome_download(udev);
		else if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001) {
			BT_INFO("FW for ar3k is yet to be downloaded");
			return -ENODEV;
		}
	}
	data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
		ep_desc = &intf->cur_altsetting->endpoint[i].desc;

		if (!data->intr_ep && usb_endpoint_is_int_in(ep_desc)) {
			data->intr_ep = ep_desc;
			continue;
		}

		if (!data->bulk_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) {
			data->bulk_tx_ep = ep_desc;
			continue;
		}

		if (!data->bulk_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) {
			data->bulk_rx_ep = ep_desc;
			continue;
		}
	}

	if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep)
		return -ENODEV;

	data->cmdreq_type = USB_TYPE_CLASS;

	data->udev = interface_to_usbdev(intf);
	data->intf = intf;

	spin_lock_init(&data->lock);

	INIT_WORK(&data->work, btusb_work);
	INIT_WORK(&data->waker, btusb_waker);
	spin_lock_init(&data->txlock);

	init_usb_anchor(&data->tx_anchor);
	init_usb_anchor(&data->intr_anchor);
	init_usb_anchor(&data->bulk_anchor);
	init_usb_anchor(&data->isoc_anchor);
	init_usb_anchor(&data->deferred);

	hdev = hci_alloc_dev();
	if (!hdev)
		return -ENOMEM;

	hdev->bus = HCI_USB;
	hci_set_drvdata(hdev, data);

	data->hdev = hdev;

	SET_HCIDEV_DEV(hdev, &intf->dev);

	hdev->open   = btusb_open;
	hdev->close  = btusb_close;
	hdev->flush  = btusb_flush;
	hdev->send   = btusb_send_frame;
	hdev->notify = btusb_notify;

	if (id->driver_info & BTUSB_BCM92035)
		hdev->setup = btusb_setup_bcm92035;

	if (id->driver_info & BTUSB_INTEL)
		hdev->setup = btusb_setup_intel;

	/* Interface numbers are hardcoded in the specification */
	data->isoc = usb_ifnum_to_if(data->udev, 1);

	if (!reset)
		set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);

	if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) {
		if (!disable_scofix)
			set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
	}

	if (id->driver_info & BTUSB_BROKEN_ISOC)
		data->isoc = NULL;

	if (id->driver_info & BTUSB_DIGIANSWER) {
		data->cmdreq_type = USB_TYPE_VENDOR;
		set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
	}

	if (id->driver_info & BTUSB_CSR) {
		struct usb_device *udev = data->udev;

		/* Old firmware would otherwise execute USB reset */
		if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117)
			set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
	}

	if (id->driver_info & BTUSB_SNIFFER) {
		struct usb_device *udev = data->udev;

		/* New sniffer firmware has crippled HCI interface */
		if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
			set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);

		data->isoc = NULL;
	}

	if (data->isoc) {
		err = usb_driver_claim_interface(&btusb_driver,
							data->isoc, data);
		if (err < 0) {
			hci_free_dev(hdev);
			return err;
		}
	}

	err = hci_register_dev(hdev);
	if (err < 0) {
		hci_free_dev(hdev);
		return err;
	}

	usb_set_intfdata(intf, data);
	usb_enable_autosuspend(data->udev);

	return 0;
}
Example #12
0
static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
{
	struct usb_wwan_intf_private *data;
	struct usb_host_interface *intf = serial->interface->cur_altsetting;
	int retval = -ENODEV;
	__u8 nintf;
	__u8 ifnum;
	bool is_gobi1k = id->driver_info ? true : false;

	dbg("%s", __func__);
	dbg("Is Gobi 1000 = %d", is_gobi1k);

	nintf = serial->dev->actconfig->desc.bNumInterfaces;
	dbg("Num Interfaces = %d", nintf);
	ifnum = intf->desc.bInterfaceNumber;
	dbg("This Interface = %d", ifnum);

	data = kzalloc(sizeof(struct usb_wwan_intf_private),
					 GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	spin_lock_init(&data->susp_lock);

	
	if (!(board_mfg_mode() == 8 || board_mfg_mode() == 6 || board_mfg_mode() == 2))
	
		usb_enable_autosuspend(serial->dev);

	switch (nintf) {
	case 1:
		
		
		if (serial->interface->num_altsetting == 2)
			intf = &serial->interface->altsetting[1];
		else if (serial->interface->num_altsetting > 2)
			break;

		if (intf->desc.bNumEndpoints == 2 &&
		    usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) &&
		    usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
			dbg("QDL port found");

			if (serial->interface->num_altsetting == 1) {
				retval = 0; 
				break;
			}

			retval = usb_set_interface(serial->dev, ifnum, 1);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		}
		break;

	case 3:
	case 4:


		if (ifnum == 1 && !is_gobi1k) {
			dbg("Gobi 2K+ DM/DIAG interface found");
			retval = usb_set_interface(serial->dev, ifnum, 0);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		} else if (ifnum == 2) {
			dbg("Modem port found");
			retval = usb_set_interface(serial->dev, ifnum, 0);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		} else if (ifnum==3 && !is_gobi1k) {
			dbg("Gobi 2K+ NMEA GPS interface found");
			retval = usb_set_interface(serial->dev, ifnum, 0);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		}
		break;

	case 9:
		
		if (get_radio_flag() & 0x20000)
		usb_diag_enable = true;
		
		if (ifnum != EFS_SYNC_IFC_NUM && !(!usb_diag_enable && ifnum == DUN_IFC_NUM && (board_mfg_mode() == 8 || board_mfg_mode() == 6 || board_mfg_mode() == 2))) { 
			kfree(data);
			break;
		}

		retval = 0;
		break;
	default:
		dev_err(&serial->dev->dev,
			"unknown number of interfaces: %d\n", nintf);
		kfree(data);
		retval = -ENODEV;
	}

	
	if (retval != -ENODEV)
		usb_set_serial_data(serial, data);
	return retval;
}
/*
 * Probe a i2400m interface and register it
 *
 * @iface:   USB interface to link to
 * @id:      USB class/subclass/protocol id
 * @returns: 0 if ok, < 0 errno code on error.
 *
 * Alloc a net device, initialize the bus-specific details and then
 * calls the bus-generic initialization routine. That will register
 * the wimax and netdev devices, upload the firmware [using
 * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the
 * communication with the device and then will start to talk to it to
 * finnish setting it up.
 */
static
int i2400mu_probe(struct usb_interface *iface,
		  const struct usb_device_id *id)
{
	int result;
	struct net_device *net_dev;
	struct device *dev = &iface->dev;
	struct i2400m *i2400m;
	struct i2400mu *i2400mu;
	struct usb_device *usb_dev = interface_to_usbdev(iface);

	if (usb_dev->speed != USB_SPEED_HIGH)
		dev_err(dev, "device not connected as high speed\n");

	/* Allocate instance [calls i2400m_netdev_setup() on it]. */
	result = -ENOMEM;
	net_dev = alloc_netdev(sizeof(*i2400mu), "wmx%d",
			       i2400mu_netdev_setup);
	if (net_dev == NULL) {
		dev_err(dev, "no memory for network device instance\n");
		goto error_alloc_netdev;
	}
	SET_NETDEV_DEV(net_dev, dev);
	SET_NETDEV_DEVTYPE(net_dev, &i2400mu_type);
	i2400m = net_dev_to_i2400m(net_dev);
	i2400mu = container_of(i2400m, struct i2400mu, i2400m);
	i2400m->wimax_dev.net_dev = net_dev;
	i2400mu->usb_dev = usb_get_dev(usb_dev);
	i2400mu->usb_iface = iface;
	usb_set_intfdata(iface, i2400mu);

	i2400m->bus_tx_block_size = I2400MU_BLK_SIZE;
	/*
	 * Room required in the Tx queue for USB message to accommodate
	 * a smallest payload while allocating header space is 16 bytes.
	 * Adding this room  for the new tx message increases the
	 * possibilities of including any payload with size <= 16 bytes.
	 */
	i2400m->bus_tx_room_min = I2400MU_BLK_SIZE;
	i2400m->bus_pl_size_max = I2400MU_PL_SIZE_MAX;
	i2400m->bus_setup = NULL;
	i2400m->bus_dev_start = i2400mu_bus_dev_start;
	i2400m->bus_dev_stop = i2400mu_bus_dev_stop;
	i2400m->bus_release = NULL;
	i2400m->bus_tx_kick = i2400mu_bus_tx_kick;
	i2400m->bus_reset = i2400mu_bus_reset;
	i2400m->bus_bm_retries = I2400M_USB_BOOT_RETRIES;
	i2400m->bus_bm_cmd_send = i2400mu_bus_bm_cmd_send;
	i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack;
	i2400m->bus_bm_mac_addr_impaired = 0;

	switch (id->idProduct) {
	case USB_DEVICE_ID_I6050:
	case USB_DEVICE_ID_I6050_2:
	case USB_DEVICE_ID_I6150:
	case USB_DEVICE_ID_I6150_2:
	case USB_DEVICE_ID_I6150_3:
	case USB_DEVICE_ID_I6250:
		i2400mu->i6050 = 1;
		break;
	default:
		break;
	}

	if (i2400mu->i6050) {
		i2400m->bus_fw_names = i2400mu_bus_fw_names_6050;
		i2400mu->endpoint_cfg.bulk_out = 0;
		i2400mu->endpoint_cfg.notification = 3;
		i2400mu->endpoint_cfg.reset_cold = 2;
		i2400mu->endpoint_cfg.bulk_in = 1;
	} else {
		i2400m->bus_fw_names = i2400mu_bus_fw_names_5x50;
		i2400mu->endpoint_cfg.bulk_out = 0;
		i2400mu->endpoint_cfg.notification = 1;
		i2400mu->endpoint_cfg.reset_cold = 2;
		i2400mu->endpoint_cfg.bulk_in = 3;
	}
#ifdef CONFIG_PM
	iface->needs_remote_wakeup = 1;		/* autosuspend (15s delay) */
	device_init_wakeup(dev, 1);
	pm_runtime_set_autosuspend_delay(&usb_dev->dev, 15000);
	usb_enable_autosuspend(usb_dev);
#endif

	result = i2400m_setup(i2400m, I2400M_BRI_MAC_REINIT);
	if (result < 0) {
		dev_err(dev, "cannot setup device: %d\n", result);
		goto error_setup;
	}
	result = i2400mu_debugfs_add(i2400mu);
	if (result < 0) {
		dev_err(dev, "Can't register i2400mu's debugfs: %d\n", result);
		goto error_debugfs_add;
	}
	return 0;

error_debugfs_add:
	i2400m_release(i2400m);
error_setup:
	usb_set_intfdata(iface, NULL);
	usb_put_dev(i2400mu->usb_dev);
	free_netdev(net_dev);
error_alloc_netdev:
	return result;
}
Example #14
0
static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
{
	struct usb_wwan_intf_private *data;
	struct usb_host_interface *intf = serial->interface->cur_altsetting;
	int retval = -ENODEV;
	__u8 nintf;
	__u8 ifnum;
	bool is_gobi1k = id->driver_info ? true : false;

	dbg("%s", __func__);
	dbg("Is Gobi 1000 = %d", is_gobi1k);

	nintf = serial->dev->actconfig->desc.bNumInterfaces;
	dbg("Num Interfaces = %d", nintf);
	ifnum = intf->desc.bInterfaceNumber;
	dbg("This Interface = %d", ifnum);

	data = kzalloc(sizeof(struct usb_wwan_intf_private),
					 GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	spin_lock_init(&data->susp_lock);

	/* ++SSD_RIL */
	if (!(board_mfg_mode() == 8 || board_mfg_mode() == 6 || board_mfg_mode() == 2))
	/* --SSD_RIL */
		usb_enable_autosuspend(serial->dev);

	switch (nintf) {
	case 1:
		/* QDL mode */
		/* Gobi 2000 has a single altsetting, older ones have two */
		if (serial->interface->num_altsetting == 2)
			intf = &serial->interface->altsetting[1];
		else if (serial->interface->num_altsetting > 2)
			break;

		if (intf->desc.bNumEndpoints == 2 &&
		    usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) &&
		    usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
			dbg("QDL port found");

			if (serial->interface->num_altsetting == 1) {
				retval = 0; /* Success */
				break;
			}

			retval = usb_set_interface(serial->dev, ifnum, 1);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		}
		break;

	case 3:
	case 4:
		/* Composite mode; don't bind to the QMI/net interface as that
		 * gets handled by other drivers.
		 */

		/* Gobi 1K USB layout:
		 * 0: serial port (doesn't respond)
		 * 1: serial port (doesn't respond)
		 * 2: AT-capable modem port
		 * 3: QMI/net
		 *
		 * Gobi 2K+ USB layout:
		 * 0: QMI/net
		 * 1: DM/DIAG (use libqcdm from ModemManager for communication)
		 * 2: AT-capable modem port
		 * 3: NMEA
		 */

		if (ifnum == 1 && !is_gobi1k) {
			dbg("Gobi 2K+ DM/DIAG interface found");
			retval = usb_set_interface(serial->dev, ifnum, 0);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		} else if (ifnum == 2) {
			dbg("Modem port found");
			retval = usb_set_interface(serial->dev, ifnum, 0);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		} else if (ifnum==3 && !is_gobi1k) {
			/*
			 * NMEA (serial line 9600 8N1)
			 * # echo "\$GPS_START" > /dev/ttyUSBx
			 * # echo "\$GPS_STOP"  > /dev/ttyUSBx
			 */
			dbg("Gobi 2K+ NMEA GPS interface found");
			retval = usb_set_interface(serial->dev, ifnum, 0);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		}
		break;
	case 8:
	case 9:
		/* ++SSD_RIL */
		if (get_radio_flag() & 0x20000)
		usb_diag_enable = true;
		/* --SSD_RIL */
		if (ifnum != EFS_SYNC_IFC_NUM && !(!usb_diag_enable && ifnum == DUN_IFC_NUM && (board_mfg_mode() == 8 || board_mfg_mode() == 6 || board_mfg_mode() == 2))) { /* SSD_RIL: Add DUN interface for serial USB*/
#ifdef CONFIG_BUILD_EDIAG
			if (ifnum != SYSMON_IFC_NUM) {
#endif
				kfree(data);
				break;
#ifdef CONFIG_BUILD_EDIAG
			}
#endif
		}
#ifdef CONFIG_BUILD_EDIAG
		if (ifnum == SYSMON_IFC_NUM)
			dev_info(&serial->dev->dev, "SYSMON device is created as TTY device\n");
#endif
		retval = 0;
		break;
	default:
		dev_err(&serial->dev->dev,
			"unknown number of interfaces: %d\n", nintf);
		kfree(data);
		retval = -ENODEV;
	}

	/* Set serial->private if not returning -ENODEV */
	if (retval != -ENODEV)
		usb_set_serial_data(serial, data);
	return retval;
}
static int rmnet_usb_probe(struct usb_interface *iface,
		const struct usb_device_id *prod)
{
	struct usbnet		*unet;
	struct driver_info	*info = (struct driver_info *)prod->driver_info;
	struct usb_device	*udev;
	int			status = 0;
	unsigned int		i, unet_id, rdev_cnt, n = 0;
	bool			mux;
	struct rmnet_ctrl_dev	*dev;

	udev = interface_to_usbdev(iface);

	if (iface->num_altsetting != 1) {
		dev_err(&iface->dev, "%s invalid num_altsetting %u\n",
			__func__, iface->num_altsetting);
		status = -EINVAL;
		goto out;
	}

	mux = test_bit(info->data, &mux_enabled);
	rdev_cnt = mux ? no_rmnet_insts_per_dev : 1;
	info->in = 0;

	for (n = 0; n < rdev_cnt; n++) {

		/*                                                      
                                                          
                                  
   */
		info->in++;
		status = usbnet_probe(iface, prod);
		if (status < 0) {
			dev_err(&iface->dev, "usbnet_probe failed %d\n",
					status);
			goto out;
		}

		unet_id = n + info->data * no_rmnet_insts_per_dev;

		unet_list[unet_id] = unet = usb_get_intfdata(iface);

		/*                             */
		unet->data[3] = n;

		/*                                            */
		unet->data[1] = unet->data[4] = mux;

		/*                                          */
		set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]);

		/*                 */
		rmnet_usb_setup(unet->net, mux);

		/*                                         */
		status = device_create_file(&unet->net->dev,
				&dev_attr_dbg_mask);
		if (status) {
			usbnet_disconnect(iface);
			goto out;
		}

		status = rmnet_usb_ctrl_probe(iface, unet->status, info->data,
				&unet->data[1]);
		if (status) {
			device_remove_file(&unet->net->dev, &dev_attr_dbg_mask);
			usbnet_disconnect(iface);
			goto out;
		}

		status = rmnet_usb_data_debugfs_init(unet);
		if (status)
			dev_dbg(&iface->dev,
					"mode debugfs file is not available\n");
	}

	usb_enable_autosuspend(udev);

	if (udev->parent && !udev->parent->parent) {
		/*                                                     */
		device_set_wakeup_enable(&udev->dev, 1);
		device_set_wakeup_enable(&udev->parent->dev, 1);
	}

	return 0;

out:
	for (i = 0; i < n; i++) {
		/*                                        */
		unet_id = i + info->data * no_rmnet_insts_per_dev;
		unet = unet_list[unet_id];
		dev = (struct rmnet_ctrl_dev *)unet->data[1];

		rmnet_usb_data_debugfs_cleanup(unet);
		rmnet_usb_ctrl_disconnect(dev);
		device_remove_file(&unet->net->dev, &dev_attr_dbg_mask);
		usb_set_intfdata(iface, unet_list[unet_id]);
		usbnet_disconnect(iface);
		unet_list[unet_id] = NULL;
	}

	return status;
}
Example #16
0
static int rmnet_usb_probe(struct usb_interface *iface,
		const struct usb_device_id *prod)
{
	struct usbnet		*unet;
	struct driver_info	*info;
	struct usb_device	*udev;
	unsigned int		iface_num;
	static int		first_rmnet_iface_num = -EINVAL;
	int			status = 0;

	iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
	if (iface->num_altsetting != 1) {
		dev_err(&iface->dev, "%s invalid num_altsetting %u\n",
			__func__, iface->num_altsetting);
		status = -EINVAL;
		goto out;
	}

	info = (struct driver_info *)prod->driver_info;
	if (!test_bit(iface_num, &info->data))
		return -ENODEV;

	status = usbnet_probe(iface, prod);
	if (status < 0) {
		dev_err(&iface->dev, "usbnet_probe failed %d\n", status);
		goto out;
	}
	unet = usb_get_intfdata(iface);

	/*set rmnet operation mode to eth by default*/
	set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]);

	/*update net device*/
	rmnet_usb_setup(unet->net);

	/*create /sys/class/net/rmnet_usbx/dbg_mask*/
	status = device_create_file(&unet->net->dev, &dev_attr_dbg_mask);
	if (status)
		goto out;

	if (first_rmnet_iface_num == -EINVAL)
		first_rmnet_iface_num = iface_num;

	/*save control device intstance */
	unet->data[1] = (unsigned long)ctrl_dev	\
			[iface_num - first_rmnet_iface_num];

	status = rmnet_usb_ctrl_probe(iface, unet->status,
		(struct rmnet_ctrl_dev *)unet->data[1]);
	if (status)
		goto out;

//ASUS_BSP+++ BennyCheng "fix rmnet driver probe fail with user build"
#ifdef CONFIG_DEBUG_FS
	status = rmnet_usb_data_debugfs_init(unet);
	if (status)
		dev_dbg(&iface->dev, "mode debugfs file is not available\n");
#endif
//ASUS_BSP--- BennyCheng "fix rmnet driver probe fail with user build"

	udev = unet->udev;

	usb_enable_autosuspend(udev);

	if (udev->parent && !udev->parent->parent) {
		/* allow modem and roothub to wake up suspended system */
		device_set_wakeup_enable(&udev->dev, 1);
		device_set_wakeup_enable(&udev->parent->dev, 1);

		/* set default autosuspend timeout for modem and roothub */
		//ASUS_BSP+++ BennyCheng "extend hsic autosuspend delay time from 1s to 2s"
		pm_runtime_set_autosuspend_delay(&udev->dev, 2000);
		//ASUS_BSP--- BennyCheng "extend hsic autosuspend delay time from 1s to 2s"
		pm_runtime_set_autosuspend_delay(&udev->parent->dev, 200);
	}

out:
	return status;
}
Example #17
0
static int chaoskey_probe(struct usb_interface *interface,
			  const struct usb_device_id *id)
{
	struct usb_device *udev = interface_to_usbdev(interface);
	struct usb_host_interface *altsetting = interface->cur_altsetting;
	int i;
	int in_ep = -1;
	struct chaoskey *dev;
	int result;
	int size;

	usb_dbg(interface, "probe %s-%s", udev->product, udev->serial);

	/* Find the first bulk IN endpoint and its packet size */
	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
		if (usb_endpoint_is_bulk_in(&altsetting->endpoint[i].desc)) {
			in_ep = usb_endpoint_num(&altsetting->endpoint[i].desc);
			size = usb_endpoint_maxp(&altsetting->endpoint[i].desc);
			break;
		}
	}

	/* Validate endpoint and size */
	if (in_ep == -1) {
		usb_dbg(interface, "no IN endpoint found");
		return -ENODEV;
	}
	if (size <= 0) {
		usb_dbg(interface, "invalid size (%d)", size);
		return -ENODEV;
	}

	if (size > CHAOSKEY_BUF_LEN) {
		usb_dbg(interface, "size reduced from %d to %d\n",
			size, CHAOSKEY_BUF_LEN);
		size = CHAOSKEY_BUF_LEN;
	}

	/* Looks good, allocate and initialize */

	dev = kzalloc(sizeof(struct chaoskey), GFP_KERNEL);

	if (dev == NULL)
		return -ENOMEM;

	dev->buf = kmalloc(size, GFP_KERNEL);

	if (dev->buf == NULL) {
		kfree(dev);
		return -ENOMEM;
	}

	/* Construct a name using the product and serial values. Each
	 * device needs a unique name for the hwrng code
	 */

	if (udev->product && udev->serial) {
		dev->name = kmalloc(strlen(udev->product) + 1 +
				    strlen(udev->serial) + 1, GFP_KERNEL);
		if (dev->name == NULL) {
			kfree(dev->buf);
			kfree(dev);
			return -ENOMEM;
		}

		strcpy(dev->name, udev->product);
		strcat(dev->name, "-");
		strcat(dev->name, udev->serial);
	}

	dev->interface = interface;

	dev->in_ep = in_ep;

	dev->size = size;
	dev->present = 1;

	init_waitqueue_head(&dev->wait_q);

	mutex_init(&dev->lock);
	mutex_init(&dev->rng_lock);

	usb_set_intfdata(interface, dev);

	result = usb_register_dev(interface, &chaoskey_class);
	if (result) {
		usb_err(interface, "Unable to allocate minor number.");
		usb_set_intfdata(interface, NULL);
		chaoskey_free(dev);
		return result;
	}

	dev->hwrng.name = dev->name ? dev->name : chaoskey_driver.name;
	dev->hwrng.read = chaoskey_rng_read;

	/* Set the 'quality' metric.  Quality is measured in units of
	 * 1/1024's of a bit ("mills"). This should be set to 1024,
	 * but there is a bug in the hwrng core which masks it with
	 * 1023.
	 *
	 * The patch that has been merged to the crypto development
	 * tree for that bug limits the value to 1024 at most, so by
	 * setting this to 1024 + 1023, we get 1023 before the fix is
	 * merged and 1024 afterwards. We'll patch this driver once
	 * both bits of code are in the same tree.
	 */
	dev->hwrng.quality = 1024 + 1023;

	dev->hwrng_registered = (hwrng_register(&dev->hwrng) == 0);
	if (!dev->hwrng_registered)
		usb_err(interface, "Unable to register with hwrng");

	usb_enable_autosuspend(udev);

	usb_dbg(interface, "chaoskey probe success, size %d", dev->size);
	return 0;
}
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 {
Example #19
0
static int chaoskey_probe(struct usb_interface *interface,
			  const struct usb_device_id *id)
{
	struct usb_device *udev = interface_to_usbdev(interface);
	struct usb_host_interface *altsetting = interface->cur_altsetting;
	struct usb_endpoint_descriptor *epd;
	int in_ep;
	struct chaoskey *dev;
	int result = -ENOMEM;
	int size;
	int res;

	usb_dbg(interface, "probe %s-%s", udev->product, udev->serial);

	/* Find the first bulk IN endpoint and its packet size */
	res = usb_find_bulk_in_endpoint(altsetting, &epd);
	if (res) {
		usb_dbg(interface, "no IN endpoint found");
		return res;
	}

	in_ep = usb_endpoint_num(epd);
	size = usb_endpoint_maxp(epd);

	/* Validate endpoint and size */
	if (size <= 0) {
		usb_dbg(interface, "invalid size (%d)", size);
		return -ENODEV;
	}

	if (size > CHAOSKEY_BUF_LEN) {
		usb_dbg(interface, "size reduced from %d to %d\n",
			size, CHAOSKEY_BUF_LEN);
		size = CHAOSKEY_BUF_LEN;
	}

	/* Looks good, allocate and initialize */

	dev = kzalloc(sizeof(struct chaoskey), GFP_KERNEL);

	if (dev == NULL)
		goto out;

	dev->buf = kmalloc(size, GFP_KERNEL);

	if (dev->buf == NULL)
		goto out;

	dev->urb = usb_alloc_urb(0, GFP_KERNEL);

	if (!dev->urb)
		goto out;

	usb_fill_bulk_urb(dev->urb,
		udev,
		usb_rcvbulkpipe(udev, in_ep),
		dev->buf,
		size,
		chaos_read_callback,
		dev);

	/* Construct a name using the product and serial values. Each
	 * device needs a unique name for the hwrng code
	 */

	if (udev->product && udev->serial) {
		dev->name = kmalloc(strlen(udev->product) + 1 +
				    strlen(udev->serial) + 1, GFP_KERNEL);
		if (dev->name == NULL)
			goto out;

		strcpy(dev->name, udev->product);
		strcat(dev->name, "-");
		strcat(dev->name, udev->serial);
	}

	dev->interface = interface;

	dev->in_ep = in_ep;

	if (le16_to_cpu(udev->descriptor.idVendor) != ALEA_VENDOR_ID)
		dev->reads_started = 1;

	dev->size = size;
	dev->present = 1;

	init_waitqueue_head(&dev->wait_q);

	mutex_init(&dev->lock);
	mutex_init(&dev->rng_lock);

	usb_set_intfdata(interface, dev);

	result = usb_register_dev(interface, &chaoskey_class);
	if (result) {
		usb_err(interface, "Unable to allocate minor number.");
		goto out;
	}

	dev->hwrng.name = dev->name ? dev->name : chaoskey_driver.name;
	dev->hwrng.read = chaoskey_rng_read;
	dev->hwrng.quality = 1024;

	dev->hwrng_registered = (hwrng_register(&dev->hwrng) == 0);
	if (!dev->hwrng_registered)
		usb_err(interface, "Unable to register with hwrng");

	usb_enable_autosuspend(udev);

	usb_dbg(interface, "chaoskey probe success, size %d", dev->size);
	return 0;

out:
	usb_set_intfdata(interface, NULL);
	chaoskey_free(dev);
	return result;
}
Example #20
0
static int hsictty_ioctl(struct tty_struct *tty, unsigned int cmd,
			 unsigned long arg)
{
	struct usb_serial_port *port = tty->driver_data;
	struct hsictty_port_private *portdata;
	struct hsictty_intf_private *intfdata;
	int channel = -1;
	int ret = -EINVAL;

	portdata = usb_get_serial_port_data(port);
	intfdata = usb_get_serial_data(port->serial);
	down(&portdata->ch_sem_w);
	down(&portdata->ch_sem_r);
	channel = tty->index;

	if (!intfdata->multi_channel_mode && channel != HSIC_DATA_START_CHANNEL) {
		hsictty_dbg("%s: invalid channel mode -- ch:%d!\n",
			    __func__, channel);
		goto out;
	}

	switch (cmd) {
	case HSIC_TTY_IOCTL_SET_MULTIMODE:
		{
			int mode = 1;
			int i = 0, j = 0;
			struct usb_serial_port *port_tmp;
			struct hsictty_port_private *portdata_tmp;
			struct urb *urb;
			if (copy_from_user(&mode, (int *)arg, sizeof(int))) {
				hsictty_error("%s: copy param failed\n",
					      __func__);
				ret = -EFAULT;
				goto out;
			}
			intfdata->multi_channel_mode = mode;
			/*set tx zlp support for multi-channel, clear tx zlp support for bootrom */
			for (i = 0; i < port->serial->num_ports; ++i) {
				port_tmp = port->serial->port[i];
				portdata_tmp =
				    usb_get_serial_port_data(port_tmp);
				for (j = 0; j < N_OUT_URB; j++) {
					urb = portdata_tmp->out_urbs[j];
					if (urb) {
						if (mode)
							urb->transfer_flags |=
							    URB_ZERO_PACKET;
						else
							urb->transfer_flags &=
							    ~URB_ZERO_PACKET;
					}
				}
			}
			hsictty_dbg
			    ("%s: set hsic tty multi-channel mode to [%d][%s] from user space!\n",
			     __func__, mode,
			     mode ? "multi-channel mode" : "single channel mode");
		}
		break;
	case HSIC_TTY_IOCTL_HSIC_RESET:
		{
			int i = 0;
			struct usb_serial_port *port_tmp;
			struct hsictty_port_private *portdata_tmp;
			//struct tty_struct *tty = NULL;
			pm_qos_update_request_timeout(&dl_kfc_num_qos, 3, 15 * 1000 * 1000);
			pm_qos_update_request_timeout(&dl_kfc_freq_qos, 1200000, 15 * 1000 * 1000);

			if (intfdata->support_pm) {
				pm_runtime_resume(&port->serial->dev->dev);
				usb_disable_autosuspend(port->serial->dev);
			}

			intfdata->multi_channel_mode = 0;
			for (i = 1; i < port->serial->num_ports; ++i) {
				port_tmp = port->serial->port[i];
				portdata_tmp =
				    usb_get_serial_port_data(port_tmp);
				portdata_tmp->opened = 0;
#ifndef USE_READ_WORK
				complete_all(&portdata_tmp->rx_notifier);
#endif
				complete_all(&portdata_tmp->tx_notifier);
				/* hangup here before diconncest marked
				 * may casue tty abnormally opened in serial core.
				tty = tty_port_tty_get(&port_tmp->port);
				if (tty) {
					tty_vhangup(tty);
					tty_kref_put(tty);
				} */
				clear_bit(i, &intfdata->channel_open_flag);
			}
#ifdef BACKUP_DATA_DUMP
			if (!dumped) {
				dumped = 1;
				backup_dump(HSIC_DATA_START_CHANNEL, 0);
				backup_dump(HSIC_DATA_START_CHANNEL, 1);
			}
#endif
			hsictty_info
			    ("%s: hsic tty reset triggerred from userspace!\n",
			     __func__);
		}
		break;
	case HSIC_TTY_IOCTL_HSIC_PM_ENABLE:
		if (intfdata->support_pm) {
			usb_enable_autosuspend(port->serial->dev);
			//pm_runtime_set_autosuspend_delay(&port->serial->dev->dev, 200);
			/* enable ehci root_hub runtime_pm */
			pm_runtime_allow(port->serial->dev->dev.parent->parent);
		}
		hsictty_info("%s: hsic pm enable from userspace!\n", __func__);
		break;
	default:
		hsictty_error("%s: illgal command !\n", __func__);
		ret = -ENOIOCTLCMD;
		goto out;

	}
	ret = 0;
out:
	up(&portdata->ch_sem_w);
	up(&portdata->ch_sem_r);

	return ret;
}
Example #21
0
static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
{
	struct usb_wwan_intf_private *data;
	struct usb_host_interface *intf = serial->interface->cur_altsetting;
	int retval = -ENODEV;
	__u8 nintf;
	__u8 ifnum;

	dbg("%s", __func__);

	nintf = serial->dev->actconfig->desc.bNumInterfaces;
	dbg("Num Interfaces = %d", nintf);
	ifnum = intf->desc.bInterfaceNumber;
	dbg("This Interface = %d", ifnum);

	data = kzalloc(sizeof(struct usb_wwan_intf_private),
					 GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	spin_lock_init(&data->susp_lock);

	usb_enable_autosuspend(serial->dev);

	switch (nintf) {
	case 1:
		/* QDL mode */
		/* Gobi 2000 has a single altsetting, older ones have two */
		if (serial->interface->num_altsetting == 2)
			intf = &serial->interface->altsetting[1];
		else if (serial->interface->num_altsetting > 2)
			break;

		if (intf->desc.bNumEndpoints == 2 &&
		    usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) &&
		    usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
			dbg("QDL port found");

			if (serial->interface->num_altsetting == 1) {
				retval = 0; /* Success */
				break;
			}

			retval = usb_set_interface(serial->dev, ifnum, 1);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		}
		break;

	case 3:
	case 4:
		/* Composite mode */
		/* ifnum == 0 is a broadband network adapter */
		if (ifnum == 1) {
			/*
			 * Diagnostics Monitor (serial line 9600 8N1)
			 * Qualcomm DM protocol
			 * use "libqcdm" (ModemManager) for communication
			 */
			dbg("Diagnostics Monitor found");
			retval = usb_set_interface(serial->dev, ifnum, 0);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		} else if (ifnum == 2) {
			dbg("Modem port found");
			retval = usb_set_interface(serial->dev, ifnum, 0);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		} else if (ifnum==3) {
			/*
			 * NMEA (serial line 9600 8N1)
			 * # echo "\$GPS_START" > /dev/ttyUSBx
			 * # echo "\$GPS_STOP"  > /dev/ttyUSBx
			 */
			dbg("NMEA GPS interface found");
			retval = usb_set_interface(serial->dev, ifnum, 0);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		}
		break;

	default:
		dev_err(&serial->dev->dev,
			"unknown number of interfaces: %d\n", nintf);
		kfree(data);
		retval = -ENODEV;
	}

	/* Set serial->private if not returning -ENODEV */
	if (retval != -ENODEV)
		usb_set_serial_data(serial, data);
	return retval;
}
static int
ksb_usb_probe(struct usb_interface *ifc, const struct usb_device_id *id)
{
	__u8				ifc_num;
	struct usb_host_interface	*ifc_desc;
	struct usb_endpoint_descriptor	*ep_desc;
	int				i;
	struct ks_bridge		*ksb;

	ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;

	switch (id->idProduct) {
	case 0x9008:
		if (ifc_num != 0)
			return -ENODEV;
		ksb = __ksb[BOOT_BRIDGE_INDEX];
		break;
	case 0x9048:
	case 0x904C:
		if (ifc_num != 2)
			return -ENODEV;
		ksb = __ksb[EFS_BRIDGE_INDEX];
		break;
	default:
		return -ENODEV;
	}

	if (!ksb) {
		pr_err("ksb is not initialized");
		return -ENODEV;
	}

	ksb->udev = usb_get_dev(interface_to_usbdev(ifc));
	ksb->ifc = ifc;
	ifc_desc = ifc->cur_altsetting;

	for (i = 0; i < ifc_desc->desc.bNumEndpoints; i++) {
		ep_desc = &ifc_desc->endpoint[i].desc;

		if (!ksb->in_epAddr && usb_endpoint_is_bulk_in(ep_desc))
			ksb->in_epAddr = ep_desc->bEndpointAddress;

		if (!ksb->out_epAddr && usb_endpoint_is_bulk_out(ep_desc))
			ksb->out_epAddr = ep_desc->bEndpointAddress;
	}

	if (!(ksb->in_epAddr && ksb->out_epAddr)) {
		pr_err("could not find bulk in and bulk out endpoints");
		usb_put_dev(ksb->udev);
		ksb->ifc = NULL;
		return -ENODEV;
	}

	ksb->in_pipe = usb_rcvbulkpipe(ksb->udev, ksb->in_epAddr);
	ksb->out_pipe = usb_sndbulkpipe(ksb->udev, ksb->out_epAddr);

	usb_set_intfdata(ifc, ksb);
	set_bit(USB_DEV_CONNECTED, &ksb->flags);

	dbg_log_event(ksb, "PID-ATT", id->idProduct, 0);

	ksb->fs_dev = (struct miscdevice *)id->driver_info;
	misc_register(ksb->fs_dev);

	ifc->needs_remote_wakeup = 1;
	usb_enable_autosuspend(ksb->udev);

	pr_debug("usb dev connected");

	return 0;
}
Example #23
0
static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
{
	struct usb_wwan_intf_private *data;
	struct usb_host_interface *intf = serial->interface->cur_altsetting;
	int retval = -ENODEV;
	__u8 nintf;
	__u8 ifnum;
	bool is_gobi1k = id->driver_info ? true : false;

	dbg("%s", __func__);
	dbg("Is Gobi 1000 = %d", is_gobi1k);

	nintf = serial->dev->actconfig->desc.bNumInterfaces;
	dbg("Num Interfaces = %d", nintf);
	ifnum = intf->desc.bInterfaceNumber;
	dbg("This Interface = %d", ifnum);

	data = kzalloc(sizeof(struct usb_wwan_intf_private),
					 GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	spin_lock_init(&data->susp_lock);
#ifdef CONFIG_MDM_HSIC_PM
	if (id->idVendor == 0x05c6 && id->idProduct == 0x9008)
		check_chip_configuration(serial->dev->product);

	if (id->idVendor == 0x05c6 &&
			(id->idProduct == 0x9008 || id->idProduct == 0x9048 ||
					id->idProduct == 0x904c))
		goto set_interface;
	usb_enable_autosuspend(serial->dev);
set_interface:
#endif
	switch (nintf) {
	case 1:
		/* QDL mode */
		/* Gobi 2000 has a single altsetting, older ones have two */
		if (serial->interface->num_altsetting == 2)
			intf = &serial->interface->altsetting[1];
		else if (serial->interface->num_altsetting > 2)
			break;

		if (intf->desc.bNumEndpoints == 2 &&
		    usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) &&
		    usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
			dbg("QDL port found");

			if (serial->interface->num_altsetting == 1) {
				retval = 0; /* Success */
				break;
			}

			retval = usb_set_interface(serial->dev, ifnum, 1);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		}
		break;

	case 3:
	case 4:
		/* Composite mode; don't bind to the QMI/net interface as that
		 * gets handled by other drivers.
		 */

		/* Gobi 1K USB layout:
		 * 0: serial port (doesn't respond)
		 * 1: serial port (doesn't respond)
		 * 2: AT-capable modem port
		 * 3: QMI/net
		 *
		 * Gobi 2K+ USB layout:
		 * 0: QMI/net
		 * 1: DM/DIAG (use libqcdm from ModemManager for communication)
		 * 2: AT-capable modem port
		 * 3: NMEA
		 */

		if (ifnum == 1 && !is_gobi1k) {
			dbg("Gobi 2K+ DM/DIAG interface found");
			retval = usb_set_interface(serial->dev, ifnum, 0);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		} else if (ifnum == 2) {
			dbg("Modem port found");
			retval = usb_set_interface(serial->dev, ifnum, 0);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		} else if (ifnum==3 && !is_gobi1k) {
			/*
			 * NMEA (serial line 9600 8N1)
			 * # echo "\$GPS_START" > /dev/ttyUSBx
			 * # echo "\$GPS_STOP"  > /dev/ttyUSBx
			 */
			dbg("Gobi 2K+ NMEA GPS interface found");
			retval = usb_set_interface(serial->dev, ifnum, 0);
			if (retval < 0) {
				dev_err(&serial->dev->dev,
					"Could not set interface, error %d\n",
					retval);
				retval = -ENODEV;
				kfree(data);
			}
		}
		break;

	case 9:
		if (ifnum != EFS_SYNC_IFC_NUM) {
			kfree(data);
			break;
		}

		retval = 0;
		break;
	default:
		dev_err(&serial->dev->dev,
			"unknown number of interfaces: %d\n", nintf);
		kfree(data);
		retval = -ENODEV;
	}

	/* Set serial->private if not returning -ENODEV */
	if (retval != -ENODEV)
		usb_set_serial_data(serial, data);
	return retval;
}
static int
ipc_bridge_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct ipc_bridge *dev;
	struct usb_device *udev = interface_to_usbdev(intf);
	struct usb_host_interface *intf_desc;
	struct usb_endpoint_descriptor *ep;
	u16 wMaxPacketSize;
	int ret;

	intf_desc = intf->cur_altsetting;
	if (intf_desc->desc.bNumEndpoints != 1 || !usb_endpoint_is_int_in(
				&intf_desc->endpoint[0].desc)) {
		dev_err(&intf->dev, "driver expects only 1 int ep\n");
		return -ENODEV;
	}

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev) {
		dev_err(&intf->dev, "fail to allocate dev\n");
		return -ENOMEM;
	}
	__ipc_bridge_dev = dev;

	dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->inturb) {
		dev_err(&intf->dev, "fail to allocate int urb\n");
		ret = -ENOMEM;
		goto free_dev;
	}

	ep = &intf->cur_altsetting->endpoint[0].desc;
	wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);

	dev->intbuf = kmalloc(wMaxPacketSize, GFP_KERNEL);
	if (!dev->intbuf) {
		dev_err(&intf->dev, "%s: error allocating int buffer\n",
			__func__);
		ret = -ENOMEM;
		goto free_inturb;
	}

	usb_fill_int_urb(dev->inturb, udev,
			usb_rcvintpipe(udev, ep->bEndpointAddress),
			dev->intbuf, wMaxPacketSize,
			ipc_bridge_int_cb, dev, ep->bInterval);

	dev->in_ctlreq = kmalloc(sizeof(*dev->in_ctlreq), GFP_KERNEL);
	if (!dev->in_ctlreq) {
		dev_err(&intf->dev, "error allocating IN control req\n");
		ret = -ENOMEM;
		goto free_intbuf;
	}

	dev->in_ctlreq->bRequestType =
			(USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
	dev->in_ctlreq->bRequest  = USB_CDC_GET_ENCAPSULATED_RESPONSE;
	dev->in_ctlreq->wValue = 0;
	dev->in_ctlreq->wIndex = intf->cur_altsetting->desc.bInterfaceNumber;
	dev->in_ctlreq->wLength = cpu_to_le16(IPC_BRIDGE_MAX_READ_SZ);

	dev->readurb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->readurb) {
		dev_err(&intf->dev, "fail to allocate read urb\n");
		ret = -ENOMEM;
		goto free_in_ctlreq;
	}

	dev->readbuf = kmalloc(IPC_BRIDGE_MAX_READ_SZ, GFP_KERNEL);
	if (!dev->readbuf) {
		dev_err(&intf->dev, "fail to allocate read buffer\n");
		ret = -ENOMEM;
		goto free_readurb;
	}

	dev->out_ctlreq = kmalloc(sizeof(*dev->out_ctlreq), GFP_KERNEL);
	if (!dev->out_ctlreq) {
		dev_err(&intf->dev, "error allocating OUT control req\n");
		ret = -ENOMEM;
		goto free_readbuf;
	}

	dev->out_ctlreq->bRequestType =
			(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
	dev->out_ctlreq->bRequest  = USB_CDC_SEND_ENCAPSULATED_COMMAND;
	dev->out_ctlreq->wValue = 0;
	dev->out_ctlreq->wIndex = intf->cur_altsetting->desc.bInterfaceNumber;

	dev->writeurb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->writeurb) {
		dev_err(&intf->dev, "fail to allocate write urb\n");
		ret = -ENOMEM;
		goto free_out_ctlreq;
	}

	dev->udev = usb_get_dev(interface_to_usbdev(intf));
	dev->intf = intf;
	spin_lock_init(&dev->lock);
	init_completion(&dev->write_done);
	init_waitqueue_head(&dev->read_wait_q);
	INIT_LIST_HEAD(&dev->rx_list);
	mutex_init(&dev->open_mutex);
	mutex_init(&dev->read_mutex);
	mutex_init(&dev->write_mutex);
	usb_set_intfdata(intf, dev);
	usb_enable_autosuspend(udev);

	dev->pdev = platform_device_alloc("ipc_bridge", -1);
	if (!dev->pdev) {
		dev_err(&intf->dev, "fail to allocate pdev\n");
		ret = -ENOMEM;
		goto destroy_mutex;
	}

	ret = platform_device_add_data(dev->pdev, &ipc_bridge_pdata,
				sizeof(struct ipc_bridge_platform_data));
	if (ret) {
		dev_err(&intf->dev, "fail to add pdata\n");
		goto put_pdev;
	}

	ret = platform_device_add(dev->pdev);
	if (ret) {
		dev_err(&intf->dev, "fail to add pdev\n");
		goto put_pdev;
	}

	ret = ipc_bridge_submit_inturb(dev, GFP_KERNEL);
	if (ret) {
		dev_err(&intf->dev, "fail to start reading\n");
		goto del_pdev;
	}

	ipc_bridge_debugfs_init();
	return 0;

del_pdev:
	platform_device_del(dev->pdev);
put_pdev:
	platform_device_put(dev->pdev);
destroy_mutex:
	usb_disable_autosuspend(udev);
	mutex_destroy(&dev->write_mutex);
	mutex_destroy(&dev->read_mutex);
	mutex_destroy(&dev->open_mutex);
	usb_put_dev(dev->udev);
	usb_free_urb(dev->writeurb);
free_out_ctlreq:
	kfree(dev->out_ctlreq);
free_readbuf:
	kfree(dev->readbuf);
free_readurb:
	usb_free_urb(dev->readurb);
free_in_ctlreq:
	kfree(dev->in_ctlreq);
free_intbuf:
	kfree(dev->intbuf);
free_inturb:
	usb_free_urb(dev->inturb);
free_dev:
	kfree(dev);
	__ipc_bridge_dev = NULL;

	return ret;
}
/* the root hub will call this callback when device added/removed */
void hsic_notify(struct usb_device *udev, unsigned action)
{
	int retval;
	struct pci_dev *pdev = to_pci_dev(udev->bus->controller);

	printk(KERN_ERR "pdev device ID: %d, portnum: %d",
			pdev->device, udev->portnum);
	/* Ignore and only valid for HSIC. Filter out
	 * the USB devices added by other USB2 host driver */
	if (pdev->device != USH_PCI_ID)
		return;

	/* Ignore USB devices on external hub */
	if (udev->parent && udev->parent->parent)
		return;

	switch (action) {
	case USB_DEVICE_ADD:
		pr_debug("Notify HSIC add device\n");
		/* Root hub */
		if (!udev->parent) {
			if (udev->speed == USB_SPEED_HIGH) {
				pr_debug("%s rh device set\n", __func__);
				hsic.rh_dev = udev;
				pr_debug("%s Disable autosuspend\n", __func__);
				pm_runtime_set_autosuspend_delay(&udev->dev,
					hsic.bus_inactivityDuration);
				usb_disable_autosuspend(udev);
			}
		} else {
			if (udev->portnum != HSIC_USH_PORT) {
				pr_debug("%s ignore ush ports except port5\n",
						__func__);
				pr_debug("%s ush ports %d\n", __func__,
						udev->portnum);
				break;
			}

			/* Modem devices */
			hsic.modem_dev = udev;
			pm_runtime_set_autosuspend_delay
				(&udev->dev, hsic.port_inactivityDuration);

			if (hsic.remoteWakeup_enable) {
				pr_debug("%s Modem dev remote wakeup enabled\n",
						 __func__);
				device_set_wakeup_capable
					(&hsic.modem_dev->dev, 1);
				device_set_wakeup_capable
					(&hsic.rh_dev->dev, 1);
			} else {
				pr_debug("%s Modem dev remote wakeup disabled\n",
						 __func__);
				device_set_wakeup_capable
					(&hsic.modem_dev->dev, 0);
				device_set_wakeup_capable
					(&hsic.rh_dev->dev, 0);
			}

			usb_disable_autosuspend(hsic.modem_dev);
			usb_disable_autosuspend(hsic.rh_dev);
#if 0
			if (hsic.autosuspend_enable) {
				pr_debug("%s----> enable autosuspend\n",
					 __func__);
				usb_enable_autosuspend(udev->parent);
				hsic_wakeup_irq_init();
			}

			if (hsic.autosuspend_enable == 0) {
				pr_debug("%s Modem dev autosuspend disable\n",
						 __func__);
				usb_disable_autosuspend(hsic.modem_dev);
			}
#endif
		}
		break;
	case USB_DEVICE_REMOVE:
		pr_debug("Notify HSIC delete device\n");
		/* Root hub */
		if (udev->speed != USB_SPEED_HIGH) {
			pr_debug("%s ignore ss port\n", __func__);
			break;
		}
		if (!udev->parent) {
			pr_debug("%s rh_dev deleted\n", __func__);
			hsic.rh_dev = NULL;
		} else {
			/* Modem devices */
			pr_debug("%s----> modem dev deleted\n", __func__);
			hsic.modem_dev = NULL;
			usb_disable_autosuspend(hsic.rh_dev);
		}
		break;
	case MODEM_WORK_FLUSH:
		if (udev == hsic.modem_dev) {
			pr_debug("Notify MODEM work flush\n");
			synchronize_irq(gpio_to_irq(hsic.aux_gpio));
			flush_work(&hsic.hsic_aux);
		}
		break;
	default:
		pr_debug("Notify action not supported\n");
		break ;
	}
	return;
}
static ssize_t hsic_port_enable_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t size)
{
	int retval;
	int org_req;

	if (size > HSIC_ENABLE_SIZE)
		return -EINVAL;

	if (sscanf(buf, "%d", &org_req) != 1) {
		dev_dbg(dev, "Invalid, value\n");
		return -EINVAL;
	}

	if (delayed_work_pending(&hsic.hsic_aux)) {
		dev_dbg(dev,
			"%s---->Wait for delayed work finish\n",
			 __func__);
		retval = wait_event_interruptible(hsic.aux_wq,
						hsic.hsic_aux_finish);
		if (retval < 0)
			return retval;

		if (org_req)
			return size;
	}

	mutex_lock(&hsic.hsic_mutex);
	if (!hsic.rh_dev) {
		dev_dbg(&pci_dev->dev,
			"root hub is already removed\n");
		mutex_unlock(&hsic.hsic_mutex);
		return -ENODEV;
	}
	if (hsic.modem_dev) {
		pm_runtime_get_sync(&hsic.modem_dev->dev);
		pm_runtime_put(&hsic.modem_dev->dev);
	}
	if (hsic.rh_dev) {
		pm_runtime_get_sync(&hsic.rh_dev->dev);
		pm_runtime_put(&hsic.rh_dev->dev);
	}

	if (hsic.port_disconnect == 0)
		hsic_port_logical_disconnect(hsic.rh_dev,
				HSIC_USH_PORT);
	else
		ush_hsic_port_disable();

	if (org_req) {
		dev_dbg(dev, "enable hsic\n");
		msleep(20);
		ush_hsic_port_enable();
	} else {
		dev_dbg(dev, "disable hsic\n");
		if ((hsic.rh_dev) && (hsic.autosuspend_enable == 0)) {
			hsic.autosuspend_enable = 1;
			usb_enable_autosuspend(hsic.rh_dev);
		}
	}
	mutex_unlock(&hsic.hsic_mutex);
	return size;
}
/* the root hub will call this callback when device added/removed */
static void hsic_notify(struct usb_device *udev, unsigned action)
{
	int retval;
	struct pci_dev *pdev = to_pci_dev(udev->bus->controller);

	/* Ignore and only valid for HSIC. Filter out
	 * the USB devices added by other USB2 host driver */
	if (pdev->device != 0x119d)
		return;

	/* Ignore USB devices on external hub */
	if (udev->parent && udev->parent->parent)
		return;

	/* Only valid for hsic port1 */
	if (udev->portnum == 2) {
		pr_debug("%s ignore hsic port2\n", __func__);
		return;
	}

	switch (action) {
	case USB_DEVICE_ADD:
		pr_debug("Notify HSIC add device\n");
		/* Root hub */
		if (!udev->parent) {
			hsic.rh_dev = udev;
			pr_debug("%s Enable autosuspend\n", __func__);
			pm_runtime_set_autosuspend_delay(&udev->dev,
					hsic.bus_inactivityDuration);
			hsic.autosuspend_enable = 1;
			usb_enable_autosuspend(udev);
		} else {
			/* Modem devices */
			hsic.modem_dev = udev;
			pm_runtime_set_autosuspend_delay
				(&udev->dev, hsic.port_inactivityDuration);
			udev->persist_enabled = 0;

			if (hsic.remoteWakeup_enable) {
				pr_debug("%s Modem dev remote wakeup enabled\n",
						 __func__);
				device_set_wakeup_capable
					(&hsic.modem_dev->dev, 1);
				device_set_wakeup_capable
					(&hsic.rh_dev->dev, 1);
			} else {
				pr_debug("%s Modem dev remote wakeup disabled\n",
						 __func__);
				device_set_wakeup_capable
					(&hsic.modem_dev->dev, 0);
				device_set_wakeup_capable
					(&hsic.rh_dev->dev, 0);
			}
			pr_debug("%s Disable autosuspend\n", __func__);
			usb_disable_autosuspend(hsic.modem_dev);
			hsic.autosuspend_enable = 0;

			pr_debug("%s----> Enable AUX irq\n", __func__);
			retval = hsic_aux_irq_init();
			if (retval)
				dev_err(&pci_dev->dev,
					"unable to request IRQ\n");
		}
		break;
	case USB_DEVICE_REMOVE:
		pr_debug("Notify HSIC delete device\n");
		/* Root hub */
		if (!udev->parent) {
			pr_debug("%s rh_dev deleted\n", __func__);
			hsic.rh_dev = NULL;
			hsic.autosuspend_enable = 1;
		} else {
			/* Modem devices */
			pr_debug("%s----> modem dev deleted\n", __func__);
			hsic.modem_dev = NULL;
		}
		s3_wake_unlock();
		break;
	default:
		pr_debug("Notify action not supported\n");
		break ;
	}
	return;
}
Example #28
0
/** 
 *  @brief This function makes USB device to suspend.
 *  
 *  @param handle  A pointer to moal_handle structure
 *
 *  @return             0 --success, otherwise fail
 */
int
woal_enter_usb_suspend(moal_handle * handle)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
#ifdef CONFIG_PM
    struct usb_device *udev = ((struct usb_card_rec *) (handle->card))->udev;
#endif /* CONFIG_PM */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
    struct usb_interface *intf = ((struct usb_card_rec *) (handle->card))->intf;
#endif /* < 2.6.34 */
#endif /* >= 2.6.24 */

    ENTER();

    if (handle->is_suspended == MTRUE) {
        PRINTM(MERROR, "Device already suspended\n");
        LEAVE();
        return -EFAULT;
    }

    handle->suspend_wait_q_woken = MFALSE;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
#ifdef CONFIG_PM
    /* Enter into USB suspend */
    usb_lock_device(udev);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
    udev->autosuspend_delay = 0;        /* Autosuspend delay in jiffies */
#else
    pm_runtime_set_autosuspend_delay(&udev->dev, 0);    /* Autosuspend delay in 
                                                           jiffies */
#endif /* < 2.6.38 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
    udev->autosuspend_disabled = 0;     /* /sys/bus/usb/devices/.../power/level 
                                           < auto */
#endif /* < 2.6.34 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
    udev->autoresume_disabled = 0;
#endif /* < 2.6.33 */
    usb_unlock_device(udev);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
    intf->pm_usage_cnt = 1;
#else
    atomic_set(&intf->pm_usage_cnt, 1);
#endif /* < 2.6.32 */
    usb_autopm_put_interface(intf);
#else
    usb_lock_device(udev);
    atomic_set(&udev->dev.power.usage_count, 1);
    usb_enable_autosuspend(udev);
    usb_unlock_device(udev);
#endif /* < 2.6.34 */
#endif /* >= 2.6.24 */
#endif /* CONFIG_PM */	//lxy

    /* Wait for suspend to complete */
    wait_event_interruptible(handle->suspend_wait_q,
                             handle->suspend_wait_q_woken);

    LEAVE();
    return 0;
}
static int rmnet_usb_probe(struct usb_interface *iface,
		const struct usb_device_id *prod)
{
	struct usbnet		*unet;
	struct driver_info	*info = (struct driver_info *)prod->driver_info;
	struct usb_device	*udev;
	int			status = 0;
	unsigned int		i, unet_id, rdev_cnt, n = 0;
	bool			mux;
	struct rmnet_ctrl_dev	*dev;

	udev = interface_to_usbdev(iface);

	if (iface->num_altsetting != 1) {
		dev_err(&iface->dev, "%s invalid num_altsetting %u\n",
			__func__, iface->num_altsetting);
		status = -EINVAL;
		goto out;
	}

	mux = test_bit(info->data, &mux_enabled);
	rdev_cnt = mux ? no_rmnet_insts_per_dev : 1;
	info->in = 0;

	for (n = 0; n < rdev_cnt; n++) {

		/* Use this filed to increment device count this will be
		 * used by bind to determin the forward link and reverse
		 * link network interface names.
		 */
		info->in++;
		status = usbnet_probe(iface, prod);
		if (status < 0) {
			dev_err(&iface->dev, "usbnet_probe failed %d\n",
					status);
			goto out;
		}

		unet_id = n + info->data * no_rmnet_insts_per_dev;

		unet_list[unet_id] = unet = usb_get_intfdata(iface);

		/*store mux id for later access*/
		unet->data[3] = n;

		/*save mux info for control and usbnet devices*/
		unet->data[1] = unet->data[4] = mux;

		/*set rmnet operation mode to eth by default*/
		set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]);

		/*update net device*/
		rmnet_usb_setup(unet->net, mux);

		/*create /sys/class/net/rmnet_usbx/dbg_mask*/
		status = device_create_file(&unet->net->dev,
				&dev_attr_dbg_mask);
		if (status) {
			usbnet_disconnect(iface);
			goto out;
		}

		status = rmnet_usb_ctrl_probe(iface, unet->status, info->data,
				&unet->data[1]);
		if (status) {
			device_remove_file(&unet->net->dev, &dev_attr_dbg_mask);
			usbnet_disconnect(iface);
			goto out;
		}

		status = rmnet_usb_data_debugfs_init(unet);
		if (status)
			dev_dbg(&iface->dev,
					"mode debugfs file is not available\n");
	}

	usb_enable_autosuspend(udev);

	if (udev->parent && !udev->parent->parent) {
		/* allow modem and roothub to wake up suspended system */
		device_set_wakeup_enable(&udev->dev, 1);
		device_set_wakeup_enable(&udev->parent->dev, 1);
	}

	return 0;

out:
	for (i = 0; i < n; i++) {
		/* This cleanup happens only for MUX case */
		unet_id = i + info->data * no_rmnet_insts_per_dev;
		unet = unet_list[unet_id];
		dev = (struct rmnet_ctrl_dev *)unet->data[1];

		rmnet_usb_data_debugfs_cleanup(unet);
		rmnet_usb_ctrl_disconnect(dev);
		device_remove_file(&unet->net->dev, &dev_attr_dbg_mask);
		usb_set_intfdata(iface, unet_list[unet_id]);
		usbnet_disconnect(iface);
		unet_list[unet_id] = NULL;
	}

	return status;
}
static void hsicdev_add(struct usb_device *udev)
{

	pr_debug("Notify HSIC add device\n");
	if (is_ush_hsic(udev) == 0) {
		pr_debug("Not a USH HSIC device\n");
		return;
	}

	/* Root hub */
	if (!udev->parent) {
		if (udev->speed == USB_SPEED_HIGH) {
			pr_debug("%s rh device set\n", __func__);
			hsic.rh_dev = udev;
			pr_debug("%s Disable autosuspend\n", __func__);
			pm_runtime_set_autosuspend_delay(&udev->dev,
				hsic.bus_inactivityDuration);
			usb_disable_autosuspend(udev);
			hsic.autosuspend_enable = 0;
		}
	} else {
		if (udev->portnum != HSIC_USH_PORT) {
			pr_debug("%s ignore ush ports %d\n",
				__func__, udev->portnum);
			return;
		}

		/* Modem devices */
		hsic.port_disconnect = 0;
		hsic.modem_dev = udev;
		pm_runtime_set_autosuspend_delay
			(&udev->dev, hsic.port_inactivityDuration);

		if (hsic.remoteWakeup_enable) {
			pr_debug("%s Modem dev remote wakeup enabled\n",
					 __func__);
			device_set_wakeup_capable
				(&hsic.modem_dev->dev, 1);
			device_set_wakeup_capable
				(&hsic.rh_dev->dev, 1);
		} else {
			pr_debug("%s Modem dev remote wakeup disabled\n",
					 __func__);
			device_set_wakeup_capable
				(&hsic.modem_dev->dev, 0);
			device_set_wakeup_capable
				(&hsic.rh_dev->dev, 0);
		}

		hsic.autosuspend_enable = HSIC_AUTOSUSPEND;
		if (hsic.autosuspend_enable) {
			pr_debug("%s----> enable autosuspend\n",
				 __func__);
			usb_enable_autosuspend(hsic.modem_dev);
			usb_enable_autosuspend(hsic.rh_dev);
			hsic_wakeup_irq_init();
		}

		if (hsic.autosuspend_enable == 0) {
			pr_debug("%s Modem dev autosuspend disable\n",
					 __func__);
			usb_disable_autosuspend(hsic.modem_dev);
			usb_disable_autosuspend(hsic.rh_dev);
		}
	}
}