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

📄 hc_isp116x.c

📁 S3C2440ARM9开发板的USB驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	int maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));	int endpoint = usb_pipeendpoint (urb->pipe);	int address = usb_pipedevice (urb->pipe);	int slow = usb_pipeslow (urb->pipe);	int out = usb_pipeout (urb->pipe);	int pid = 0;	int ret;	int i;	int iso = 0; 	dbg("transfer_pa: addr: %d, ep:%d, out:%x in:%x\n", 	    address, endpoint, urb->dev->toggle[1], urb->dev->toggle[0]);	if (maxps == 0) maxps = 8;	/* calculate len, toggle bit and add the transaction */	switch (usb_pipetype (urb->pipe)) {		case PIPE_ISOCHRONOUS:			iso = 1;			i = hci->frame_no - urb->start_frame;			data = urb->transfer_buffer + urb->iso_frame_desc[i].offset;			len = urb->iso_frame_desc[i].length;			break;					case PIPE_BULK: /* BULK and BULK0 */		case PIPE_INTERRUPT:			pid = out ? PID_OUT : PID_IN;				len = urb->transfer_buffer_length - urb->actual_length;			data = urb->transfer_buffer + urb->actual_length;			toggle = usb_gettoggle (urb->dev, endpoint, out);			break;		case PIPE_CONTROL:			switch (qu_urbstate (urb)) {				case US_CTRL_SETUP:						len = 8;					pid = PID_SETUP;					data = urb->setup_packet;					toggle = 0;					break;				case US_CTRL_DATA:					if (urb->transfer_buffer_length != 0) {						pid = out ? PID_OUT : PID_IN;							len = urb->transfer_buffer_length - urb->actual_length;						data = urb->transfer_buffer + urb->actual_length;						toggle = (urb->actual_length & maxps) ? 0 : 1;						break;					} else						/* correct state and fall through */						qu_seturbstate (urb, US_CTRL_ACK);										case US_CTRL_ACK:					len = 0;					/* reply in opposite direction */					pid = !out ? PID_OUT : PID_IN; 					toggle = 1;					break;			}	}	ret = hc_add_trans (hci, len, data, toggle, maxps, slow, 						endpoint, address, pid, iso);	if (ret) {		hci->urb_array [hci->trans] = urb;		hci->trans ++;		if (usb_pipetype (urb->pipe) == PIPE_INTERRUPT)			 urb->start_frame = hci->frame_no;	}	return ret;}/*-------------------------------------------------------------------------*//* parse the done_list * */static int sh_done_list (hci_t * hci) {	int actbytes;	int active = 0;	void * data = NULL; 	void * data_urb = NULL;	int cc;	int maxps;	int toggle;	struct urb * urb;	int urb_state;	int ret = 1; /* -1 parse abbort, 1 parse ok, 0 last element */	int trans = 0;	for (trans = 0; trans < hci->trans; trans++) {		urb = hci->urb_array [trans];		if (urb->dev == 0) {			printk("hc_isp1116x: urb on done list has no device.\n");			continue;		}		urb_state = qu_urbstate (urb);		toggle = usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), 					usb_pipeout (urb->pipe));			ret = hc_parse_trans (hci, &actbytes, &data, &cc, &toggle);		maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));		if (maxps == 0) maxps = 8;		if (cc != TD_NOTACCESSED) {			active = (urb_state != US_CTRL_SETUP) && 					(actbytes && !(actbytes & (maxps - 1)) &&					(urb->transfer_buffer_length != urb->actual_length + actbytes));			data_urb = urb->transfer_buffer + urb->actual_length;			if (!(urb->transfer_flags & USB_DISABLE_SPD) && cc == TD_DATAUNDERRUN)								cc = 0;			if (cc) { /* last packet has an error */				if (hc_error_verbose)					printk("hc USB %d error %d in frame %d ep %d out %d addr %d\n", 						urb->error_count, cc, hci->frame_no, 							usb_pipeendpoint (urb->pipe),							usb_pipeout (urb->pipe), usb_pipedevice (urb->pipe));				if (++urb->error_count > 3 || cc == TD_CC_STALL) {					active = 0;					urb_state = 0; /* return */				} else { 			//		actbytes = actbytes & ~(maxps - 1);					actbytes = 0;					active = 1;				}			} else if (urb_state != US_CTRL_SETUP) { /* no error */				if (!usb_pipeout (urb->pipe) && actbytes && data_urb != data)					memcpy (data_urb, data, actbytes);				urb->actual_length += actbytes;				usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), 					usb_pipeout (urb->pipe), 					!toggle);//					(!actbytes || !((actbytes - 1) & maxps) ? !toggle : toggle));			}						if (!active) {				if (!(urb_state--)) {					urb->status = cc_to_error [cc];					qu_return_urb (hci, urb, 1);				} else {					qu_seturbstate (urb, urb_state);				}			}		}	}		return ret;}/*-------------------------------------------------------------------------*//* scan the delete list (qu_return_urb removes URB from list)  * */static void sh_del_list (hci_t * hci) {	struct list_head * lh = &hci->del_list;	struct urb * urb;	if (!list_empty (lh)) {		do {			lh = lh->next;			urb = list_entry (lh, struct urb, urb_list);			qu_return_urb (hci, urb, 0);		} while (!list_empty (lh));				wake_up (&hci->waitq);	}	return;}	/*------------------------------------------------------------------------- * ISP116x virtual root hub * From hc_isp116x_rh.c by Roman Weissgaerber weissg@vienna.at *-------------------------------------------------------------------------*//*-------------------------------------------------------------------------* * Virtual Root Hub  *-------------------------------------------------------------------------*/ /* Device descriptor */static __u8 root_hub_dev_des[] ={	0x12,       /*  __u8  bLength; */	0x01,       /*  __u8  bDescriptorType; Device */	0x10,	    /*  __u16 bcdUSB; v1.1 */	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; */	0x02,       /*  __u8  iProduct; */	0x01,       /*  __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 */ 	0x02,       /*  __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ 	0x00,	0xff        /*  __u8  ep_bInterval; 255 ms */};/* Hub class-specific descriptor is constructed dynamically *//*-------------------------------------------------------------------------*//* prepare Interrupt pipe data; HUB INTERRUPT ENDPOINT */  static int rh_send_irq (hci_t * hci, void * rh_data, int rh_len){	int num_ports;	int i;	int ret;	int len;	u8 data[8];	num_ports = READ_REG32 (hci, HcRhDescriptorA) & RH_A_NDP; 		data[0] = (READ_REG32 (hci, HcRhStatus) & (RH_HS_LPSC | RH_HS_OCIC))		? 1 : 0;	ret = data[0];	for (i = 0; i < num_ports; i++) {		u32 reg = READ_REG32(hci, HcRhPortStatus + i);		data[(i + 1) / 8] |= 			((reg &			 (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | RH_PS_PRSC))			    ? 1 : 0) << ((i + 1) % 8);		ret += data[(i + 1) / 8] ;	}	len = i/8 + 1;  	if (ret > 0) { 		memcpy (rh_data, data, min(len, min_t(int,rh_len, sizeof(data))));		return len;	}	return 0;}/*-------------------------------------------------------------------------*//* Virtual Root Hub INTs are polled by this timer every "interval" ms */ static void rh_int_timer_do (unsigned long ptr){	int len; 	struct urb * urb = (struct urb *) ptr;	hci_t * hci = urb->dev->bus->hcpriv;#if 0 /* cleanup? */	if (hci->disabled)//		return;	/* ignore timers firing during PM suspend, etc */	if ((hci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER)		goto out;#endif	if(hci->rh.send) { 		len = rh_send_irq (hci, urb->transfer_buffer, urb->transfer_buffer_length);		if (len > 0) {			urb->actual_length = len;			if (urb_debug == 2)				urb_print (urb, "RET-t(rh)", usb_pipeout (urb->pipe));			if (urb->complete)				urb->complete (urb);		}	}// out:	rh_init_int_timer (urb);}/*-------------------------------------------------------------------------*//* Root Hub INTs are polled by this timer */static int rh_init_int_timer (struct urb * urb) {	hci_t * hci = urb->dev->bus->hcpriv;	hci->rh.interval = urb->interval;	init_timer (&hci->rh.rh_int_timer);	hci->rh.rh_int_timer.function = rh_int_timer_do;	hci->rh.rh_int_timer.data = (unsigned long) urb;	hci->rh.rh_int_timer.expires = 			jiffies + (HZ * (urb->interval < 30? 30: urb->interval)) / 1000;	add_timer (&hci->rh.rh_int_timer);		return 0;}/*-------------------------------------------------------------------------*/#define OK(x) 			len = (x); break#define WR_RH_STAT(x) 		WRITE_REG32 (hci, (x), HcRhStatus)#define WR_RH_PORTSTAT(x) 	WRITE_REG32 (hci, (x), HcRhPortStatus + wIndex - 1)#define RD_RH_STAT		READ_REG32 (hci, HcRhStatus)#define RD_RH_PORTSTAT		READ_REG32 (hci, HcRhPortStatus + wIndex - 1)/* request to virtual root hub */static int rh_submit_urb (struct urb * urb){	struct usb_device * usb_dev = urb->dev;	hci_t * hci = usb_dev->bus->hcpriv;	unsigned int pipe = urb->pipe;	struct usb_ctrlrequest * cmd = (struct usb_ctrlrequest *) urb->setup_packet;	void * data = urb->transfer_buffer;	int leni = urb->transfer_buffer_length;	int len = 0;	int status = TD_CC_NOERROR;		__u32 datab[4];	__u8  * data_buf = (__u8 *) datab;	 	__u16 bmRType_bReq;	__u16 wValue; 	__u16 wIndex;	__u16 wLength;	if (usb_pipeint(pipe)) {		hci->rh.urb =  urb;		hci->rh.send = 1;		hci->rh.interval = urb->interval;		rh_init_int_timer(urb);		urb->status = cc_to_error [TD_CC_NOERROR];				return 0;	}	bmRType_bReq  = cmd->bRequestType | (cmd->bRequest << 8);	wValue        = le16_to_cpu (cmd->wValue);	wIndex        = le16_to_cpu (cmd->wIndex);	wLength       = le16_to_cpu (cmd->wLength);	dbg ("rh_submit_urb, req = %d(%x) len=%d", bmRType_bReq,		bmRType_bReq, 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_buf = cpu_to_le16 (1); OK (2);	case RH_GET_STATUS | RH_INTERFACE: 	 				*(__u16 *) data_buf = cpu_to_le16 (0); OK (2);	case RH_GET_STATUS | RH_ENDPOINT:	 				*(__u16 *) data_buf = cpu_to_le16 (0); OK (2);   	case RH_GET_STATUS | RH_CLASS: 						*(__u32 *) data_buf = cpu_to_le32 (			RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));		OK (4);	case RH_GET_STATUS | RH_OTHER | RH_CLASS: 			*(__u32 *) data_buf = cpu_to_le32 (RD_RH_PORTSTAT); 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_LOCAL_POWER:			OK(0);		case (RH_C_HUB_OVER_CURRENT): 			WR_RH_STAT(RH_HS_OCIC); OK (0);		}		break;			case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:		switch (wValue) {		case (RH_PORT_ENABLE): 						WR_RH_PORTSTAT (RH_PS_CCS ); OK (0);		case (RH_PORT_SUSPEND):						WR_RH_PORTSTAT (RH_PS_POCI); OK (0);		case (RH_PORT_POWER):						WR_RH_PORTSTAT (RH_PS_LSDA); OK (0);		case (RH_C_PORT_CONNECTION):				WR_RH_PORTSTAT (RH_PS_CSC ); OK (0);		case (RH_C_PORT_ENABLE):					WR_RH_PORTSTAT (RH_PS_PESC); OK (0);		case (RH_C_PORT_SUSPEND):					WR_RH_PORTSTAT (RH_PS_PSSC); OK (0);		case (RH_C_PORT_OVER_CURRENT):				WR_RH_PORTSTAT (RH_PS_OCIC); OK (0);		case (RH_C_PORT_RESET):						WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); 		}		break;			case RH_SET_FEATURE | RH_OTHER | RH_CLASS:		switch (wValue) {		case (RH_PORT_SUSPEND):						WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); 		case (RH_PORT_RESET): /* BUG IN HUB CODE *********/			if (RD_RH_PORTSTAT & RH_PS_CCS)				WR_RH_PORTSTAT (RH_PS_PRS);			OK (0);		case (RH_PORT_POWER):						WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); 		case (RH_PORT_ENABLE): /* BUG IN HUB CODE *********/			if (RD_RH_PORTSTAT & RH_PS_CCS)				WR_RH_PORTSTAT (RH_PS_PES );			OK (0);		}		break;			case RH_SET_ADDRESS: hci->rh.devnum = wValue; OK(0);			case RH_GET_DESCRIPTOR:		switch ((wValue & 0xff00) >> 8) {		case (0x01): /* device descriptor */			len = min (leni, min_t(int, sizeof (root_hub_dev_des), wLength));			data_buf = root_hub_dev_des; OK(len);		case (0x02): /* configuration descriptor */			len = min (leni, min_t(int, sizeof (root_hub_config_des), wLength));			data_buf = root_hub_config_des; OK(len);		case (0x03): /* string descriptors */			len = usb_root_hub_string (wValue & 0xff,						   (int)(long) 0, "ISP116x",						   data, wLength);			if (len > 0) {				data_buf = data;				OK (min (leni, len));			}			// else fallthrough		default: 			status = TD_CC_STALL;		}		break;			case RH_GET_DESCRIPTOR | RH_CLASS:	{		__u32 temp = READ_REG32 (hci, HcRhDescriptorA);				data_buf [0] = 9;		// min length;		data_buf [1] = 0x29;		data_buf [2] = temp & RH_A_NDP;		data_buf [3] = 0;		if (temp & RH_A_PSM) 	/* per-port power switching? */			data_buf [3] |= 0x1;		if (temp & RH_A_NOCP)	/* no overcurrent reporting? */			data_buf [3] |= 0x10;		else if (temp & RH_A_OCPM)	/* per-port overcurrent reporting? */			data_buf [3] |= 0x8;				datab [1] = 0;		data_buf [5] = (temp & RH_A_POTPGT) >> 24;		temp = READ_REG32 (hci, HcRhDescriptorB);		data_buf [7] = temp & RH_B_DR;		if (data_buf [2] < 7) {			data_buf [8] = 0xff;		} else {				data_buf [0] += 2;				data_buf [8] = (temp & RH_B_DR) >> 8;				data_buf [10] = data_buf [9] = 0xff;		}				len = min (leni, min_t(int, data_buf [0], wLength));		OK (len);	}		case RH_GET_CONFIGURATION: 	*(__u8 *) data_buf = 0x01; OK (1);			case RH_SET_CONFIGURATION: 	WR_RH_STAT (0x10000); OK (0);			default: 		dbg ("unsupported root hub command");		status = TD_CC_STALL;	}		len = min(len, leni);	if (data != data_buf)	    memcpy (data, data_buf, len);  	urb->actual_length = len;	urb->status = cc_to_error [status];		// hci_return_urb (hci, urb, NULL); 	urb->hcpriv = NULL;	urb->dev = NULL;	if (urb->complete)	    	urb->complete (urb);		return 0;}/*-------------------------------------------------------------------------*/static int rh_unlink_urb (struct urb * urb){	hci_t * hci = urb->dev->bus->hcpriv; 	if (hci->rh.urb == urb) {		hci->rh.send = 0;		del_timer (&hci->rh.rh_int_timer);		hci->rh.urb = NULL;		urb->hcpriv = NULL;		urb->dev = NULL;		if (urb->transfer_flags & USB_ASYNC_UNLINK) {			urb->status = -ECONNRESET;			if (urb->complete)				urb->complete (urb);		} else			urb->status = -ENOENT;	}	return 0;}/*-------------------------------------------------------------------------*//* connect the virtual root hub */ static int rh_connect_rh (hci_t * hci) {         struct usb_device  * usb_dev;         hci->rh.devnum = 0;        usb_dev = usb_alloc_dev (NULL, hci->bus);        if (!usb_dev)            return -ENOMEM;         hci->bus->root_hub = usb_dev;        usb_connect (usb_dev);        if (usb_new_device (usb_dev) != 0) {                usb_free_dev (usb_dev);                return -ENODEV;        }         return 0;} 

⌨️ 快捷键说明

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