Beispiel #1
0
void wakeup_device(struct usb_serial_port *port, u8 if_pull_GPIO)
{
	int err;
	int cnt = 12;
	struct hsictty_port_private *portdata;
	struct hsictty_intf_private *intfdata;

	portdata = usb_get_serial_port_data(port);
	intfdata = usb_get_serial_data(port->serial);

	if (if_pull_GPIO) {
		/* prevent system going to suspend as urb queued
		 * deffer urb at beginning of resume until system ready
		 */
		while (sys_suspending && cnt--)
			usleep_range(10 * 1000, 10 * 1000 + 1000);

		if (sys_suspending)
			hsictty_error("%s: sys not ready, longer ??\n", __func__);

		err = usb_autopm_get_interface(port->serial->interface);
	} else {
		err = usb_autopm_get_interface_async(port->serial->interface);
	}
	if (err < 0) {
		hsictty_error
		    ("%s: auto pm get error[%d] in channel:%d, pm cnt:%d\n",
		     __func__, err, portdata->channel,
		     atomic_read(&port->serial->interface->dev.power.
				 usage_count));
		usb_autopm_get_interface_no_resume(port->serial->interface);
	}
}
static int cdc_ether_resume(struct usb_interface *intf)
{
	int ret;
#ifdef CONFIG_HAS_WAKELOCK
	struct usbnet        *dev = usb_get_intfdata(intf);
	struct cdc_state     *info = (void *) &dev->data;
#endif /* CONFIG_HAS_WAKELOCK */
	ret = usbnet_resume(intf);
#ifdef CONFIG_HAS_WAKELOCK
	if (!ret && dev->driver_info->flags & FLAG_WAKELOCK) {
		wake_lock(&info->wake_lock);
	}
#endif /* CONFIG_HAS_WAKELOCK */

	/* Force autopm to schedule an auto suspend */
	usb_autopm_get_interface_no_resume(intf);
	usb_autopm_put_interface_async(intf);

	return ret;
}
Beispiel #3
0
static void sierra_close(struct usb_serial_port *port)
{
	int i;
	struct usb_serial *serial = port->serial;
	struct sierra_port_private *portdata;
	struct sierra_intf_private *intfdata = usb_get_serial_data(serial);
	struct urb *urb;

	portdata = usb_get_serial_port_data(port);

	/*
	 * Need to take susp_lock to make sure port is not already being
	 * resumed, but no need to hold it due to initialized
	 */
	spin_lock_irq(&intfdata->susp_lock);
	if (--intfdata->open_ports == 0)
		serial->interface->needs_remote_wakeup = 0;
	spin_unlock_irq(&intfdata->susp_lock);

	for (;;) {
		urb = usb_get_from_anchor(&portdata->delayed);
		if (!urb)
			break;
		kfree(urb->transfer_buffer);
		usb_free_urb(urb);
		usb_autopm_put_interface_async(serial->interface);
		spin_lock(&portdata->lock);
		portdata->outstanding_urbs--;
		spin_unlock(&portdata->lock);
	}

	sierra_stop_rx_urbs(port);
	usb_kill_anchored_urbs(&portdata->active);

	for (i = 0; i < portdata->num_in_urbs; i++) {
		sierra_release_urb(portdata->in_urbs[i]);
		portdata->in_urbs[i] = NULL;
	}

	usb_autopm_get_interface_no_resume(serial->interface);
}
static void notification_available_cb(struct urb *urb)
{
	int				status;
	struct usb_cdc_notification	*ctrl;
	struct ctrl_bridge		*dev = urb->context;
	struct bridge			*brdg = dev->brdg;
	unsigned int			ctrl_bits;
	unsigned char			*data;
	unsigned long			flags;

	/*usb device disconnect*/
	if (urb->dev->state == USB_STATE_NOTATTACHED)
		return;

	spin_lock_irqsave(&dev->lock, flags);
	dev->rx_state = RX_IDLE;
	spin_unlock_irqrestore(&dev->lock, flags);

	switch (urb->status) {
	case 0:
		/*success*/
		break;
	case -ESHUTDOWN:
	case -ENOENT:
	case -ECONNRESET:
	case -EPROTO:
		 /* unplug */
		 return;
	case -EPIPE:
		dev_err(&dev->intf->dev,
			"%s: stall on int endpoint\n", __func__);
		/* TBD : halt to be cleared in work */
	case -EOVERFLOW:
	default:
		pr_debug_ratelimited("%s: non zero urb status = %d\n",
					__func__, urb->status);
		goto resubmit_int_urb;
	}

	ctrl = (struct usb_cdc_notification *)urb->transfer_buffer;
	data = (unsigned char *)(ctrl + 1);

	switch (ctrl->bNotificationType) {
	case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
		spin_lock_irqsave(&dev->lock, flags);
		dev->rx_state = RX_BUSY;
		spin_unlock_irqrestore(&dev->lock, flags);
		dev->resp_avail++;
		usb_autopm_get_interface_no_resume(dev->intf);
		usb_fill_control_urb(dev->readurb, dev->udev,
					usb_rcvctrlpipe(dev->udev, 0),
					(unsigned char *)dev->in_ctlreq,
					dev->readbuf,
					DEFAULT_READ_URB_LENGTH,
					resp_avail_cb, dev);

		status = usb_submit_urb(dev->readurb, GFP_ATOMIC);
		if (status) {
			dev_err(&dev->intf->dev,
				"%s: Error submitting Read URB %d\n",
				__func__, status);
			usb_autopm_put_interface_async(dev->intf);
			goto resubmit_int_urb;
		}
		return;
	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
		dev_dbg(&dev->intf->dev, "%s network\n", ctrl->wValue ?
					"connected to" : "disconnected from");
		break;
	case USB_CDC_NOTIFY_SERIAL_STATE:
		dev->notify_ser_state++;
		ctrl_bits = get_unaligned_le16(data);
		dev_dbg(&dev->intf->dev, "serial state: %d\n", ctrl_bits);
		dev->cbits_tohost = ctrl_bits;
		if (brdg && brdg->ops.send_cbits)
			brdg->ops.send_cbits(brdg->ctx, ctrl_bits);
		break;
	default:
		dev_err(&dev->intf->dev, "%s: unknown notification %d received:"
			"index %d len %d data0 %d data1 %d",
			__func__, ctrl->bNotificationType, ctrl->wIndex,
			ctrl->wLength, data[0], data[1]);
	}

resubmit_int_urb:
	ctrl_bridge_start_read(dev, GFP_ATOMIC);
}
//probe书中有教
static int our_probe(struct usb_interface *intf,
			 const struct usb_device_id *id){
struct us_data *us;
int result;
//device
struct device *dev;
//scsihost
struct Scsi_Host *host;
//检测id是否符合 和intf
struct us_unusual_dev *unusual_dev;

unusual_dev=(id - usb_storage_usb_ids) + us_unusual_dev_list;
if(usb_usual_check_type(id,USB_US_TYPE_STOR) || usb_usual_ignore_device(intf))
return -ENXIO;

printk(KERN_ALERT "probe usb   usb  detected!\n");
//分配个host

host = scsi_host_alloc(&usb_stor_host_template,sizeof(*us));
if(!host){
dev_warn(&intf->dev,"fail to allocate the scsi host\n");
return -ENOMEM;
}
//host中的一些初始化
host->max_cmd_len = 16;
host-> sg_tablesize = usb_stor_sg_tablesize(intf);
us= host_to_us(host);//us 作为host中 的us
//分内存?
memset(us,0,sizeof(struct us_data));
mutex_init(&(us->dev_mutex));
init_completion(&us->cmnd_ready);
init_completion(&(us->notify));
init_waitqueue_head(&us->delay_wait);
INIT_DELAYED_WORK(&us->scan_dwork,usb_stor_scan_dwork);

result = associate_dev(us,intf);
if(result)
         goto Bad;
result = get_device_info(us,id,unusual_dev);
if(result)
         goto Bad;
//transport protocol
get_transport(us);
get_protocol(us);

if(!us->transport ||!us->proto_handler){
result=-ENXIO;
goto Bad;
}
printk(KERN_ALERT"Transport: %s\n",us->transport_name);
printk(KERN_ALERT"Protocol: %s\n",us->transport_name);
dev = &us->pusb_intf->dev;
//设置max lun
if(us->fflags & US_FL_SINGLE_LUN)
us->max_lun =0;

//endpoint get pipe
result = get_pipes(us);
if(result)
goto Bad;
//如果u盘前十个指令错误,重置
if (us->fflags & US_FL_INITIAL_READ10)
		set_bit(US_FLIDX_REDO_READ10, &us->dflags);
//申请子资源,添加进host
result=usb_stor_acquire_sesources(us);
if(result)
goto Bad;
snprintf(us->scsi_name,sizeof(us->scsi_name),"our-usb-storage%s",dev_name(&us->pusb_intf->dev));
result= scsi_add_host(us_to_host(us),dev);
if(result){
printk(KERN_ALERT"UNable to add the host\n");
goto Bad;
}
//scsi设备延时探测
usb_autopm_get_interface_no_resume(us->pusb_intf);
set_bit(US_FLIDX_SCAN_PENDING,&us->dflags);
if(delay_use>0)
          dev_dbg(dev,"waiting for device before scanning\n");
queue_delayed_work(system_freezable_wq,&us->scan_dwork,delay_use * HZ);


return 0;
Bad:

 printk(KERN_ALERT "probe false!\n");
release_everything(us);
return result;
   }
static void ipc_bridge_int_cb(struct urb *urb)
{
	struct ipc_bridge *dev = urb->context;
	struct usb_cdc_notification *ctl;
	int status;
	unsigned long flags;

	if (urb->dev->state == USB_STATE_NOTATTACHED)
		return;

	spin_lock_irqsave(&dev->lock, flags);
	dev->rx_state = RX_IDLE;
	spin_unlock_irqrestore(&dev->lock, flags);

	switch (urb->status) {
	case 0:
	case -ENOENT:
		break;

	case -ESHUTDOWN:
	case -ECONNRESET:
	case -EPROTO:
	case -EPIPE:
		return;

	case -EOVERFLOW:
	default:
		ipc_bridge_submit_inturb(dev, GFP_ATOMIC);
		return;
	}

	if (!urb->actual_length)
		return;

	ctl = urb->transfer_buffer;

	switch (ctl->bNotificationType) {
	case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:

		spin_lock_irqsave(&dev->lock, flags);
		dev->rx_state = RX_BUSY;
		spin_unlock_irqrestore(&dev->lock, flags);

		usb_fill_control_urb(dev->readurb, dev->udev,
				usb_rcvctrlpipe(dev->udev, 0),
				(unsigned char *)dev->in_ctlreq,
				dev->readbuf, IPC_BRIDGE_MAX_READ_SZ,
				ipc_bridge_read_cb, dev);

		status = usb_submit_urb(dev->readurb, GFP_ATOMIC);
		if (status) {
			dev_err(&dev->intf->dev, "read urb submit err %d\n",
					status);
			goto resubmit_int_urb;
		}
		dev->get_encap_resp++;
		/* Tell runtime pm core that we are busy */
		usb_autopm_get_interface_no_resume(dev->intf);
		return;
	default:
		dev_err(&dev->intf->dev, "unknown data on int ep\n");
	}

resubmit_int_urb:
	ipc_bridge_submit_inturb(dev, GFP_ATOMIC);
}