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

📄 sl811.c

📁 在LINUX下驱动USB芯片SL811的程序源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	case RH_GET_DESCRIPTOR | USB_TYPE_CLASS:		len = sizeof(sl811_rh_hub_des);		bufp = sl811_rh_hub_des;		OK(len);	case RH_GET_CONFIGURATION:		bufp[0] = 0x01;		OK(1);	case RH_SET_CONFIGURATION:		OK(0);	default:		PDEBUG(1, "unsupported root hub command");		status = -EPIPE;	}	len = min(len, buf_len);	if (data != bufp)		memcpy(data, bufp, len);	urb->actual_length = len;	urb->status = status;	PDEBUG(5, "len = %d, status = %d", len, status);	urb->hcpriv = NULL;	urb->dev = NULL;	if (urb->complete)		urb->complete(urb);	return 0;}/* * This function unlinks the URB */static int sl811_rh_unlink_urb(struct urb *urb){	struct sl811_hc *hc = urb->dev->bus->hcpriv;	PDEBUG(5, "enter");	if (hc->rh.urb == urb) {		hc->rh.send = 0;		del_timer(&hc->rh.rh_int_timer);		hc->rh.urb = NULL;		urb->hcpriv = NULL;		usb_dec_dev_use(urb->dev);		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;}/* * This function connect the virtual root hub to the USB stack */static int sl811_connect_rh(struct sl811_hc * hc){	struct usb_device *usb_dev;	hc->rh.devnum = 0;	usb_dev = usb_alloc_dev(NULL, hc->bus);	if (!usb_dev)		return -ENOMEM;	hc->bus->root_hub = usb_dev;	usb_connect(usb_dev);	if (usb_new_device(usb_dev)) {		usb_free_dev(usb_dev);		return -ENODEV;	}		PDEBUG(5, "leave success");	return 0;}/* * This function allocates private data space for the usb device */static int sl811_alloc_dev_priv(struct usb_device *usb_dev){	return 0;}/* * This function de-allocates private data space for the usb devic */static int sl811_free_dev_priv (struct usb_device *usb_dev){	return 0;}/* * This function allocates private data space for the urb */static struct sl811_urb_priv* sl811_alloc_urb_priv(struct urb *urb){	struct sl811_urb_priv *urbp;		urbp = kmalloc(sizeof(*urbp), GFP_KERNEL);	if (!urbp)		return NULL;		memset(urbp, 0, sizeof(*urbp));		INIT_LIST_HEAD(&urbp->td_list);		urbp->urb = urb;	urb->hcpriv = urbp;		return urbp;}/* * This function free private data space for the urb */static void sl811_free_urb_priv(struct urb *urb){	struct sl811_urb_priv *urbp = urb->hcpriv;	struct sl811_td *td;	struct list_head *head, *tmp;		if (!urbp)		return ;		head = &urbp->td_list;	tmp = head->next;		while (tmp != head) {		td = list_entry(tmp, struct sl811_td, td_list);		tmp = tmp->next;		kfree(td);	}		kfree(urbp);	urb->hcpriv = NULL;		return ;}/* * This	function calculate the bus time need by this td. * Fix me! Can this use usb_calc_bus_time()? */static void sl811_calc_td_time(struct sl811_td *td){#if 1	int time;	int len = td->len;	struct sl811_hc *hc = td->urb->dev->bus->hcpriv; 	if (hc->rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED)		time = 8*8*len + 1024;	else {		if (td->ctrl & SL811_USB_CTRL_PREAMBLE)			time = 8*8*len + 2048;		else			time = 8*len + 256;	}	time += 2*10 * len;	td->bustime = time;	#else	unsigned long tmp;	int time;	int low_speed = usb_pipeslow(td->urb->pipe);	int input_dir = usb_pipein(td->urb->pipe);	int bytecount = td->len;	int isoc = usb_pipeisoc(td->urb->pipe); 	if (low_speed) {	/* no isoc. here */		if (input_dir) {			tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L;			time =  (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);		} else {			tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L;			time =  (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);		}	} else if (!isoc){	/* for full-speed: */		tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;		time = (9107L + BW_HOST_DELAY + tmp);	} else {		/* for isoc: */		tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;		time =  (((input_dir) ? 7268L : 6265L) + BW_HOST_DELAY + tmp);	}		td->bustime = time / 84;#endif		 }/* * This	function calculate the remainder bus time in current frame. */static inline int sl811_calc_bus_remainder(struct sl811_hc *hc){	return (sl811_read(hc, SL811_SOFCNTDIV) * 64);}/* * This function allocates td for the urb */static struct sl811_td* sl811_alloc_td(struct urb *urb){	struct sl811_urb_priv *urbp = urb->hcpriv;	struct sl811_td *td;		td = kmalloc(sizeof (*td), GFP_KERNEL);	if (!td)		return NULL;		memset(td, 0, sizeof(*td));		INIT_LIST_HEAD(&td->td_list);		td->urb = urb;	list_add_tail(&td->td_list, &urbp->td_list);		return td;}/* * Fill the td. */static inline void sl811_fill_td(struct sl811_td *td, __u8 ctrl, __u8 addr, __u8 len, __u8 pidep, __u8 dev, __u8 *buf){	td->ctrl = ctrl;	td->addr = addr;	td->len = len;	td->pidep = pidep;	td->dev = dev;	td->buf = buf;	td->left = len;	td->errcnt = 3;}/* * Fill the td. */static inline void sl811_reset_td(struct sl811_td *td){	td->status = 0;	td->left = td->len;	td->done = 0;	td->errcnt = 3;	td->nakcnt = 0;	td->td_status = 0;}static void sl811_print_td(int level, struct sl811_td *td){	 PDEBUG(level, "td = %p, ctrl = %x, addr = %x, len = %x, pidep = %x\n "		"dev = %x, status = %x, left = %x, errcnt = %x, done = %x\n "		"buf = %p, bustime = %d, td_status = %d\n", 		td, td->ctrl, td->addr, td->len, td->pidep,		td->dev, td->status, td->left, td->errcnt, td->done,		td->buf, td->bustime, td->td_status);}/* * Isochronous transfers */static int sl811_submit_isochronous(struct urb *urb){	__u8 dev = usb_pipedevice(urb->pipe);	__u8 pidep = PIDEP(usb_packetid(urb->pipe), usb_pipeendpoint(urb->pipe));	__u8 ctrl = 0;	struct sl811_urb_priv *urbp = urb->hcpriv;	struct sl811_td *td = NULL;	int i;		PDEBUG(4, "enter, urb = %p, urbp = %p", urb, urbp);	/* Can't have low speed bulk transfers */	if (usb_pipeslow(urb->pipe)) {		PDEBUG(1, "error, urb = %p, low speed device", urb);		return -EINVAL;	}		if (usb_pipeout(urb->pipe))		ctrl |= SL811_USB_CTRL_DIR_OUT;			ctrl |= SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE | SL811_USB_CTRL_ISO;		for (i = 0; i < urb->number_of_packets; i++) {		urb->iso_frame_desc[i].actual_length = 0;		urb->iso_frame_desc[i].status = -EXDEV;					td = sl811_alloc_td(urb);		if (!td)			return -ENOMEM;		sl811_fill_td(td, ctrl, SL811_DATA_START, 			urb->iso_frame_desc[i].length,			pidep, dev,			urb->transfer_buffer + urb->iso_frame_desc[i].offset);		sl811_calc_td_time(td);		if (urbp->cur_td == NULL)			urbp->cur_td = urbp->first_td = td;		}	urbp->last_td = td;			PDEBUG(4, "leave success");/*	// for debug	{		struct list_head *head, *tmp;		struct sl811_td *td;		int i = 0;		head = &urbp->td_list;		tmp = head->next;			if (list_empty(&urbp->td_list)) {			PDEBUG(1, "bug!!! td list is empty!");			return -ENODEV;		}				while (tmp != head) {			++i;			td = list_entry(tmp, struct sl811_td, td_list);			PDEBUG(2, "td = %p, i = %d", td, i);			tmp = tmp->next;		}	}*/		return 0;}/* * Reset isochronous transfers */static void sl811_reset_isochronous(struct urb *urb){	struct sl811_urb_priv *urbp = urb->hcpriv;	struct sl811_td *td = NULL;	struct list_head *head, *tmp;	int i;	PDEBUG(4, "enter, urb = %p", urb);	for (i = 0; i < urb->number_of_packets; i++) {		urb->iso_frame_desc[i].actual_length = 0;		urb->iso_frame_desc[i].status = -EXDEV;	}	head = &urbp->td_list;	tmp = head->next;	while (tmp != head) {		td = list_entry(tmp, struct sl811_td, td_list);		tmp = tmp->next;		sl811_reset_td(td);	}		urbp->cur_td = urbp->first_td;		urb->status = -EINPROGRESS;	urb->actual_length = 0;	urb->error_count = 0;}/* * Result the iso urb. */static void sl811_result_isochronous(struct urb *urb){	struct list_head *tmp, *head;	struct sl811_urb_priv *urbp = urb->hcpriv;	int status = 0;	struct sl811_td *td;	int i;	PDEBUG(4, "enter, urb = %p", urb);	urb->actual_length = 0;	i = 0;	head = &urbp->td_list;	tmp = head->next;	while (tmp != head) {		td = list_entry(tmp, struct sl811_td, td_list);		tmp = tmp->next;				if (!td->done) {			if (urbp->unlink)				urb->status = -ENOENT;			else {				PDEBUG(1, "we should not get here!");				urb->status = -EXDEV;			}			return ;			}		if (td->td_status) {			status = td->td_status;			urb->error_count++;			PDEBUG(1, "error: td = %p, td status = %d", td, td->td_status);		}		urb->iso_frame_desc[i].actual_length = td->len - td->left;		urb->actual_length += td->len - td->left;		urb->iso_frame_desc[i].status = td->td_status;		++i;		if (td->left)			PDEBUG(3, "short packet, td = %p, len = %d, left = %d", td, td->len, td->left);	}	urb->status = status;/*// for debug	PDEBUG(2, "iso urb complete, len = %d, status =%d ", urb->actual_length, urb->status);		*/	PDEBUG(4, "leave success");}/* * Interrupt transfers */static int sl811_submit_interrupt(struct urb *urb){	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));	int len = urb->transfer_buffer_length;	__u8 *data = urb->transfer_buffer;	__u8 dev = usb_pipedevice(urb->pipe);	__u8 pidep = PIDEP(usb_packetid(urb->pipe), usb_pipeendpoint(urb->pipe));	__u8 ctrl = 0;	struct sl811_hc *hc = urb->dev->bus->hcpriv;	struct sl811_urb_priv *urbp = urb->hcpriv;	struct sl811_td *td = NULL;		PDEBUG(4, "enter, urb = %p", urb);	if (len > maxsze) {		PDEBUG(1, "length is big than max packet size, len = %d, max packet = %d", len, maxsze);		return -EINVAL;	}	if (usb_pipeslow(urb->pipe) && !(hc->rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED))		ctrl |= SL811_USB_CTRL_PREAMBLE;		ctrl |= SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE;	if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)))		ctrl |= SL811_USB_CTRL_TOGGLE_1;	usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));		td = sl811_alloc_td(urb);	if (!td)		return -ENOMEM;			sl811_fill_td(td, ctrl, SL811_DATA_START, len, pidep, dev, data);	sl811_calc_td_time(td);	urbp->cur_td = urbp->first_td = urbp->last_td = td;	urbp->interval = 0;		PDEBUG(4, "leave success");	return 0;}/* * Reset interrupt transfers */static void sl811_reset_interrupt(struct urb *urb){	struct sl811_urb_priv *urbp = urb->hcpriv;	struct sl811_td *td = urbp->cur_td;		PDEBUG(4, "enter, interval = %d", urb->interval);	td->ctrl &= ~SL811_USB_CTRL_TOGGLE_1;	if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)))		td->ctrl |= SL811_USB_CTRL_TOGGLE_1;	usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));			sl811_reset_td(td);	urbp->interval = urb->interval;		urb->status = -EINPROGRESS;	urb->actual_length = 0;}/* * Result the interrupt urb. */static void sl811_result_interrupt(struct urb *urb){	struct list_head *tmp;	struct sl811_urb_priv *urbp = urb->hcpriv;	struct sl811_td *td;	int toggle;		PDEBUG(4, "enter, urb = %p", urb);	urb->actual_length = 0;	tmp = &urbp->td_list;	tmp = tmp->next;	td = list_entry(tmp, struct sl811_td, td_list);	// success.	if (td->done && td->td_status == 0) {		urb->actual_length += td->len - td->left;		urb->status = 0;		return ;	}	// tranfer is done but fail, reset the toggle.	else if (td->done && td->td_status) {		urb->status = td->td_status;reset_toggle:		toggle = (td->ctrl & SL811_USB_CTRL_TOGGLE_1) ? 1 : 0;		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), toggle);		PDEBUG(3, "error: td = %p, td status = %d", td, td->td_status);		return ;	}	// unlink, and not do transfer yet	else if (td->done == 0 && urbp->unlink && td->td_status == 0) {		urb->status = -ENOENT;		PDEBUG(3, "unlink and not transfer!");		return ;	}	// unlink, and transfer not complete yet.	else if (td->done == 0 && urbp->unlink && td->td_status) {		urb->status = -ENOENT;		PDEBUG(3, "unlink and not complete!");		goto reset_toggle;	}	// must be bug!!!	else {// (td->done == 0 && urbp->unlink == 0)		PDEBUG(1, "we should not get here!");		urb->status = -EPIPE;		return ;	}}/* * Control transfers */static int sl811_submit_control(struct urb *urb){	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));	int len = urb->transfer_buffer_length;	__u8 *data = urb->transfer_buffer;	__u8 dev = usb_pipedevice(urb->pipe);	__u8 pidep = 0;	__u8 ctrl = 0;	struct sl811_hc *hc = urb->dev->bus->hcpriv;	struct sl811_urb_priv *urbp = urb->hcpriv;	struct sl811_td *td = NULL;

⌨️ 快捷键说明

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