⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb-uhci.c

📁 Usb1.1驱动c语言源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		return -ENODEV;	s = (uhci_t*) urb->dev->bus->hcpriv;	//dbg("submit_urb: %p type %d",urb,usb_pipetype(urb->pipe));		if (!s->running)		return -ENODEV;			if (usb_pipedevice (urb->pipe) == s->rh.devnum)		return rh_submit_urb (urb);	/* virtual root hub */	usb_inc_dev_use (urb->dev);	spin_lock_irqsave (&s->urb_list_lock, flags);	bulk_urb = search_dev_ep (s, urb);	if (bulk_urb) {		queue_dbg("found bulk urb %p\n",bulk_urb);		if ((usb_pipetype (urb->pipe) != PIPE_BULK) ||		    ((usb_pipetype (urb->pipe) == PIPE_BULK) &&		     (!(urb->transfer_flags & USB_QUEUE_BULK) || !(bulk_urb->transfer_flags & USB_QUEUE_BULK)))) {			spin_unlock_irqrestore (&s->urb_list_lock, flags);			usb_dec_dev_use (urb->dev);			err("ENXIO1 %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,bulk_urb);			return -ENXIO;	// urb already queued		}	}#ifdef DEBUG_SLAB	urb_priv = kmem_cache_alloc(urb_priv_kmem, SLAB_FLAG);#else	urb_priv = kmalloc (sizeof (urb_priv_t), KMALLOC_FLAG);#endif	if (!urb_priv) {		usb_dec_dev_use (urb->dev);		spin_unlock_irqrestore (&s->urb_list_lock, flags);		return -ENOMEM;	}	urb->hcpriv = urb_priv;	INIT_LIST_HEAD (&urb_priv->desc_list);	urb_priv->short_control_packet = 0;	dbg("submit_urb: scheduling %p", urb);	urb_priv->next_queued_urb = NULL;	urb_priv->prev_queued_urb = NULL;	urb_priv->bottom_qh = NULL;	urb_priv->next_qh = NULL;		if (usb_pipetype (urb->pipe) == PIPE_BULK) {			if (bulk_urb) {			while (((urb_priv_t*)bulk_urb->hcpriv)->next_queued_urb)  // find last queued bulk				bulk_urb=((urb_priv_t*)bulk_urb->hcpriv)->next_queued_urb;						((urb_priv_t*)bulk_urb->hcpriv)->next_queued_urb=urb;		}		atomic_inc (&s->avoid_bulk);		ret = uhci_submit_bulk_urb (urb, bulk_urb);		atomic_dec (&s->avoid_bulk);		spin_unlock_irqrestore (&s->urb_list_lock, flags);	}	else {		spin_unlock_irqrestore (&s->urb_list_lock, flags);		switch (usb_pipetype (urb->pipe)) {		case PIPE_ISOCHRONOUS:			ret = uhci_submit_iso_urb (urb);			break;		case PIPE_INTERRUPT:			ret = uhci_submit_int_urb (urb);			break;		case PIPE_CONTROL:			ret = uhci_submit_control_urb (urb);			break;		default:			ret = -EINVAL;		}	}	dbg("submit_urb: scheduled with ret: %d", ret);		if (ret != 0) {		usb_dec_dev_use (urb->dev);#ifdef DEBUG_SLAB		kmem_cache_free(urb_priv_kmem, urb_priv);#else		kfree (urb_priv);#endif		return ret;	}	return 0;}// Checks for URB timeout and removes bandwidth reclamation // if URB idles too long_static void uhci_check_timeouts(uhci_t *s){	struct list_head *p,*p2;	urb_t *urb;	int type;		p = s->urb_list.prev;		while (p != &s->urb_list) {		urb_priv_t *hcpriv;		p2 = p;		p = p->prev;		urb = list_entry (p2, urb_t, urb_list);		type = usb_pipetype (urb->pipe);		hcpriv = (urb_priv_t*)urb->hcpriv;						if ( urb->timeout && 			((hcpriv->started + urb->timeout) < jiffies)) {			urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK;			async_dbg("uhci_check_timeout: timeout for %p",urb);			uhci_unlink_urb_async(s, urb);		}#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH		else if (((type == PIPE_BULK) || (type == PIPE_CONTROL)) &&  		     (hcpriv->use_loop) &&		     ((hcpriv->started + IDLE_TIMEOUT) < jiffies))			disable_desc_loop(s, urb);#endif	}}/*------------------------------------------------------------------- Virtual Root Hub -------------------------------------------------------------------*/_static __u8 root_hub_dev_des[] ={	0x12,			/*  __u8  bLength; */	0x01,			/*  __u8  bDescriptorType; Device */	0x00,			/*  __u16 bcdUSB; v1.0 */	0x01,	0x09,			/*  __u8  bDeviceClass; HUB_CLASSCODE */	0x00,			/*  __u8  bDeviceSubClass; */	0x00,			/*  __u8  bDeviceProtocol; */	0x08,			/*  __u8  bMaxPacketSize0; 8 Bytes */	0x00,			/*  __u16 idVendor; */	0x00,	0x00,			/*  __u16 idProduct; */	0x00,	0x00,			/*  __u16 bcdDevice; */	0x00,	0x00,			/*  __u8  iManufacturer; */	0x00,			/*  __u8  iProduct; */	0x00,			/*  __u8  iSerialNumber; */	0x01			/*  __u8  bNumConfigurations; */};/* Configuration descriptor */_static __u8 root_hub_config_des[] ={	0x09,			/*  __u8  bLength; */	0x02,			/*  __u8  bDescriptorType; Configuration */	0x19,			/*  __u16 wTotalLength; */	0x00,	0x01,			/*  __u8  bNumInterfaces; */	0x01,			/*  __u8  bConfigurationValue; */	0x00,			/*  __u8  iConfiguration; */	0x40,			/*  __u8  bmAttributes; 				   Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */	0x00,			/*  __u8  MaxPower; */     /* interface */	0x09,			/*  __u8  if_bLength; */	0x04,			/*  __u8  if_bDescriptorType; Interface */	0x00,			/*  __u8  if_bInterfaceNumber; */	0x00,			/*  __u8  if_bAlternateSetting; */	0x01,			/*  __u8  if_bNumEndpoints; */	0x09,			/*  __u8  if_bInterfaceClass; HUB_CLASSCODE */	0x00,			/*  __u8  if_bInterfaceSubClass; */	0x00,			/*  __u8  if_bInterfaceProtocol; */	0x00,			/*  __u8  if_iInterface; */     /* endpoint */	0x07,			/*  __u8  ep_bLength; */	0x05,			/*  __u8  ep_bDescriptorType; Endpoint */	0x81,			/*  __u8  ep_bEndpointAddress; IN Endpoint 1 */	0x03,			/*  __u8  ep_bmAttributes; Interrupt */	0x08,			/*  __u16 ep_wMaxPacketSize; 8 Bytes */	0x00,	0xff			/*  __u8  ep_bInterval; 255 ms */};_static __u8 root_hub_hub_des[] ={	0x09,			/*  __u8  bLength; */	0x29,			/*  __u8  bDescriptorType; Hub-descriptor */	0x02,			/*  __u8  bNbrPorts; */	0x00,			/* __u16  wHubCharacteristics; */	0x00,	0x01,			/*  __u8  bPwrOn2pwrGood; 2ms */	0x00,			/*  __u8  bHubContrCurrent; 0 mA */	0x00,			/*  __u8  DeviceRemovable; *** 7 Ports max *** */	0xff			/*  __u8  PortPwrCtrlMask; *** 7 ports max *** */};/*-------------------------------------------------------------------------*//* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */_static int rh_send_irq (urb_t *urb){	int len = 1;	int i;	uhci_t *uhci = urb->dev->bus->hcpriv;	unsigned int io_addr = uhci->io_addr;	__u16 data = 0;	for (i = 0; i < uhci->rh.numports; i++) {		data |= ((inw (io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0);		len = (i + 1) / 8 + 1;	}	*(__u16 *) urb->transfer_buffer = cpu_to_le16 (data);	urb->actual_length = len;	urb->status = 0;		if ((data > 0) && (uhci->rh.send != 0)) {		dbg("Root-Hub INT complete: port1: %x port2: %x data: %x",		     inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2), data);		urb->complete (urb);	}	return 0;}/*-------------------------------------------------------------------------*//* Virtual Root Hub INTs are polled by this timer every "intervall" ms */_static int rh_init_int_timer (urb_t *urb);_static void rh_int_timer_do (unsigned long ptr){	int len;	urb_t *urb = (urb_t*) ptr;	uhci_t *uhci = urb->dev->bus->hcpriv;	if (uhci->rh.send) {		len = rh_send_irq (urb);		if (len > 0) {			urb->actual_length = len;			if (urb->complete)				urb->complete (urb);		}	}	rh_init_int_timer (urb);}/*-------------------------------------------------------------------------*//* Root Hub INTs are polled by this timer, polling interval 20ms *//* This time is also used for URB-timeout checking */_static int rh_init_int_timer (urb_t *urb){	uhci_t *uhci = urb->dev->bus->hcpriv;	uhci->rh.interval = urb->interval;	init_timer (&uhci->rh.rh_int_timer);	uhci->rh.rh_int_timer.function = rh_int_timer_do;	uhci->rh.rh_int_timer.data = (unsigned long) urb;	uhci->rh.rh_int_timer.expires = jiffies + (HZ * 20) / 1000;	add_timer (&uhci->rh.rh_int_timer);	return 0;}/*-------------------------------------------------------------------------*/#define OK(x) 			len = (x); break#define CLR_RH_PORTSTAT(x) \		status = inw(io_addr+USBPORTSC1+2*(wIndex-1)); \		status = (status & 0xfff5) & ~(x); \		outw(status, io_addr+USBPORTSC1+2*(wIndex-1))#define SET_RH_PORTSTAT(x) \		status = inw(io_addr+USBPORTSC1+2*(wIndex-1)); \		status = (status & 0xfff5) | (x); \		outw(status, io_addr+USBPORTSC1+2*(wIndex-1))/*-------------------------------------------------------------------------*//**** ** Root Hub Control Pipe *************************/_static int rh_submit_urb (urb_t *urb){	struct usb_device *usb_dev = urb->dev;	uhci_t *uhci = usb_dev->bus->hcpriv;	unsigned int pipe = urb->pipe;	devrequest *cmd = (devrequest *) urb->setup_packet;	void *data = urb->transfer_buffer;	int leni = urb->transfer_buffer_length;	int len = 0;	int status = 0;	int stat = 0;	int i;	unsigned int io_addr = uhci->io_addr;	__u16 cstatus;	__u16 bmRType_bReq;	__u16 wValue;	__u16 wIndex;	__u16 wLength;	if (usb_pipetype (pipe) == PIPE_INTERRUPT) {		dbg("Root-Hub submit IRQ: every %d ms", urb->interval);		uhci->rh.urb = urb;		uhci->rh.send = 1;		uhci->rh.interval = urb->interval;		rh_init_int_timer (urb);		return 0;	}	bmRType_bReq = cmd->requesttype | cmd->request << 8;	wValue = le16_to_cpu (cmd->value);	wIndex = le16_to_cpu (cmd->index);	wLength = le16_to_cpu (cmd->length);	for (i = 0; i < 8; i++)		uhci->rh.c_p_r[i] = 0;	dbg("Root-Hub: adr: %2x cmd(%1x): %04x %04x %04x %04x",	     uhci->rh.devnum, 8, bmRType_bReq, wValue, wIndex, wLength);	switch (bmRType_bReq) {		/* Request Destination:		   without flags: Device, 		   RH_INTERFACE: interface, 		   RH_ENDPOINT: endpoint,		   RH_CLASS means HUB here, 		   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here 		 */	case RH_GET_STATUS:		*(__u16 *) data = cpu_to_le16 (1);		OK (2);	case RH_GET_STATUS | RH_INTERFACE:		*(__u16 *) data = cpu_to_le16 (0);		OK (2);	case RH_GET_STATUS | RH_ENDPOINT:		*(__u16 *) data = cpu_to_le16 (0);		OK (2);	case RH_GET_STATUS | RH_CLASS:		*(__u32 *) data = cpu_to_le32 (0);		OK (4);		/* hub power ** */	case RH_GET_STATUS | RH_OTHER | RH_CLASS:		status = inw (io_addr + USBPORTSC1 + 2 * (wIndex - 1));		cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) |			((status & USBPORTSC_PEC) >> (3 - 1)) |			(uhci->rh.c_p_r[wIndex - 1] << (0 + 4));		status = (status & USBPORTSC_CCS) |			((status & USBPORTSC_PE) >> (2 - 1)) |			((status & USBPORTSC_SUSP) >> (12 - 2)) |			((status & USBPORTSC_PR) >> (9 - 4)) |			(1 << 8) |	/* power on ** */			((status & USBPORTSC_LSDA) << (-8 + 9));		*(__u16 *) data = cpu_to_le16 (status);		*(__u16 *) (data + 2) = cpu_to_le16 (cstatus);		OK (4);	case RH_CLEAR_FEATURE | RH_ENDPOINT:		switch (wValue) {		case (RH_ENDPOINT_STALL):			OK (0);		}		break;	case RH_CLEAR_FEATURE | RH_CLASS:		switch (wValue) {		case (RH_C_HUB_OVER_CURRENT):			OK (0);	/* hub power over current ** */		}		break;	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:		switch (wValue) {		case (RH_PORT_ENABLE):			CLR_RH_PORTSTAT (USBPORTSC_PE);			OK (0);		case (RH_PORT_SUSPEND):			CLR_RH_PORTSTAT (USBPORTSC_SUSP);			OK (0);		case (RH_PORT_POWER):			OK (0);	/* port power ** */		case (RH_C_PORT_CONNECTION):			SET_RH_PORTSTAT (USBPORTSC_CSC);			OK (0);		case (RH_C_PORT_ENABLE):			SET_RH_PORTSTAT (USBPORTSC_PEC);			OK (0);		case (RH_C_PORT_SUSPEND):/*** WR_RH_PORTSTAT(RH_PS_PSSC); */			OK (0);		case (RH_C_PORT_OVER_CURRENT):			OK (0);	/* port power over current ** */		case (RH_C_PORT_RESET):			uhci->rh.c_p_r[wIndex - 1] = 0;			OK (0);		}		break;	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:		switch (wValue) {		case (RH_PORT_SUSPEND):			SET_RH_PORTSTAT (USBPORTSC_SUSP);			OK (0);		case (RH_PORT_RESET):			SET_RH_PORTSTAT (USBPORTSC_PR);			uhci_wait_ms (10);			uhci->rh.c_p_r[wIndex - 1] = 1;			CLR_RH_PORTSTAT (USBPORTSC_PR);			udelay (10);			SET_RH_PORTSTAT (USBPORTSC_PE);			uhci_wait_ms (10);			SET_RH_PORTSTAT (0xa);			OK (0);		case (RH_PORT_POWER):			OK (0);	/* port power ** */		case (RH_PORT_ENABLE):			SET_RH_PORTSTAT (USBPORTSC_PE);			OK (0);		}		break;	case RH_SET_ADDRESS:		uhci->rh.devnum = wValue;		OK (0);	case RH_GET_DESCRIPTOR:		switch ((wValue & 0xff00) >> 8) {		case (0x01):	/* device descriptor */			len = min (leni, min (sizeof (root_hub_dev_des), wLength));			memcpy (data, root_hub_dev_des, len);			OK (len);		case (0x02):	/* configuration descriptor */			len = min (leni, min (sizeof (root_hub_config_des), wLength));			memcpy (data, root_hub_config_des, len);			OK (len);		case (0x03):	/*string descriptors */			stat = -EPIPE;		}		break;	case RH_GET_DESCRIPTOR | RH_CLASS:		root_hub_hub_des[2] = uhci->rh.numports;		len = min (leni, min (sizeof (root_hub_hub_des), wLength));		memcpy (data, root_hub_hub_des, len);		OK (len);	case RH_GET_CONFIGURATION:		*(__u8 *) data = 0x01;		OK (1);	case RH_SET_CONFIGURATION:		OK (0);	default:		stat = -EPIPE;	}	dbg("Root-Hub stat port1: %x port2: %x",	     inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2));	urb->actual_length = len;	urb->status = stat;	if (urb->complete)		urb->complete (urb);	return 0;}/*-------------------------------------------------------------------------*/_static int rh_unlink_urb (urb_t *urb){	uhci_t *uhci = urb->dev->bus->hcpriv;	if (uhci->rh.urb==urb) {		dbg("Root-Hub unlink IRQ");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -