usbd-bi.c

来自「Linux2.4.20针对三星公司的s3c2440内核基础上的一些设备驱动代码」· C语言 代码 · 共 1,414 行 · 第 1/3 页

C
1,414
字号
		break;	case DEVICE_BUS_INACTIVE:		// disable suspend interrupt		udc_suspended_interrupts (device);		// XXX check on linkup and sl11		// if we are no longer connected then force a reset		if (!udc_connected ()) {			usbd_device_event_irq (device, DEVICE_RESET, 0);		}		break;	case DEVICE_BUS_ACTIVITY:		// enable suspend interrupt		udc_all_interrupts (device);		break;	case DEVICE_POWER_INTERRUPTION:		break;	case DEVICE_HUB_RESET:		break;	case DEVICE_DESTROY:		udc_disconnect ();		bi_disable_endpoints (device);		udc_disable_interrupts (device);		udc_disable ();		break;	case DEVICE_FUNCTION_PRIVATE:		break;	}	return 0;}/** * bi_send_urb - start transmit * @urb: */int bi_send_urb (struct urb *urb){	unsigned long flags;	dbg_tx (4, "urb: %p", urb);	local_irq_save (flags);	if (urb && urb->endpoint && !urb->endpoint->tx_urb) {		dbg_tx (2, "urb: %p endpoint: %x", urb, urb->endpoint->endpoint_address);		usbd_tx_complete_irq (urb->endpoint, 0);		udc_start_in_irq (urb->endpoint);	}	local_irq_restore (flags);	// Shouldn't need to make this atomic, all we need is a change indicator	urb->device->usbd_rxtx_timestamp = jiffies;	return 0;}#if defined(CONFIG_PM) && !defined(CONFIG_USBD_MONITOR) && !defined(CONFIG_USBD_MONITOR_MODULE)static int bi_pm_event (struct pm_dev *pm_dev, pm_request_t request, void *unused);#endifstruct usb_bus_operations bi_ops = {	send_urb:bi_send_urb,	cancel_urb:bi_cancel_urb,	endpoint_halted:bi_endpoint_halted,	device_feature:bi_device_feature,	device_event:bi_device_event,};struct usb_bus_driver bi_driver = {	name:"",	max_endpoints:0,	ops:&bi_ops,	this_module:THIS_MODULE,};/* Bus Interface Received Data *************************************************************** */struct usb_device_instance *device_array[MAX_DEVICES];/* Bus Interface Support Functions *********************************************************** *//** * udc_cable_event - called from cradle interrupt handler */void udc_cable_event (void){	struct usb_bus_instance *bus;	struct usb_device_instance *device;	struct bi_data *data;	dbgENTER (dbgflg_usbdbi_init, 1);	// sanity check	if (!(device = device_array[0]) || !(bus = device->bus) || !(data = bus->privdata)) {		return;	}	{		unsigned long flags;		local_irq_save (flags);		if (udc_connected ()) {			dbg_init (1, "state: %d connected: %d", device->device_state, 1);;			if (device->device_state == STATE_ATTACHED) {				dbg_init (1, "LOADING");				usbd_device_event_irq (device, DEVICE_HUB_CONFIGURED, 0);				usbd_device_event_irq (device, DEVICE_RESET, 0);			}		} else {			dbg_init (1, "state: %d connected: %d", device->device_state, 0);;			if (device->device_state != STATE_ATTACHED) {				dbg_init (1, "UNLOADING");				usbd_device_event_irq (device, DEVICE_RESET, 0);				usbd_device_event_irq (device, DEVICE_POWER_INTERRUPTION, 0);				usbd_device_event_irq (device, DEVICE_HUB_RESET, 0);			}		}		local_irq_restore (flags);	}	dbgLEAVE (dbgflg_usbdbi_init, 1);}/* Module Init - the device init and exit routines ******************************************* *//** * bi_udc_init - initialize USB Device Controller *  * Get ready to use the USB Device Controller. * * Register an interrupt handler and IO region. Return non-zero for error. */int bi_udc_init (void){	dbg_init (1, "Loading %s", udc_name ());	bi_driver.name = udc_name ();	bi_driver.max_endpoints = udc_max_endpoints ();	bi_driver.maxpacketsize = udc_ep0_packetsize ();	dbg_init (1, "name: %s endpoints: %d ep0: %d", bi_driver.name, bi_driver.max_endpoints,		  bi_driver.maxpacketsize);	// request device IRQ	if (udc_request_udc_irq ()) {		dbg_init (0, "name: %s request udc irq failed", udc_name ());		return -EINVAL;	}	// request device IO	if (udc_request_io ()) {		udc_release_udc_irq ();		dbg_init (0, "name: %s request udc io failed", udc_name ());		return -EINVAL;	}	// probe for device	if (udc_init ()) {		udc_release_udc_irq ();		udc_release_io ();		dbg_init (1, "name: %s probe failed", udc_name ());		return -EINVAL;	}	// optional cable IRQ 	have_cable_irq = !udc_request_cable_irq ();	dbg_init (1, "name: %s request cable irq %d", udc_name (), have_cable_irq);	return 0;}/** * bi_udc_exit - Stop using the USB Device Controller * * Stop using the USB Device Controller. * * Shutdown and free dma channels, de-register the interrupt handler. */void bi_udc_exit (void){	int i;	dbg_init (1, "Unloading %s", udc_name ());	for (i = 0; i < udc_max_endpoints (); i++) {		udc_disable_ep (i);	}	// free io and irq	udc_disconnect ();	udc_disable ();	udc_release_io ();	udc_release_udc_irq ();	if (have_cable_irq) {		udc_release_cable_irq ();	}}/* Module Init - the module init and exit routines ************************************* */#if 0/* bi_init - commission bus interface driver */static int bi_init (void){	return 0;}#endif/* bi_exit - decommission bus interface driver */static void bi_exit (void){}#if defined(CONFIG_PM) && !defined(CONFIG_USBD_MONITOR) && !defined(CONFIG_USBD_MONITOR_MODULE)/* Module Init - Power management ************************************************************ *//* The power management scheme is simple. Simply do the following: * *      Event           Call            Equivalent *      ------------------------------------------ *      PM_SUSPEND      bi_exit();      rmmod *      PM_RESUME       bi_init();      insmod * */static int pm_suspended;/* * usbd_pm_callback * @dev: * @rqst: * @unused: * * Used to signal power management events. */static int bi_pm_event (struct pm_dev *pm_dev, pm_request_t request, void *unused){	struct usb_device_instance *device;	dbg_pm (0, "request: %d pm_dev: %p data: %p", request, pm_dev, pm_dev->data);	if (!(device = pm_dev->data)) {		dbg_pm (0, "DATA NULL, NO DEVICE");		return 0;	}	switch (request) {#if defined(CONFIG_IRIS)	case PM_STANDBY:	case PM_BLANK:#endif	case PM_SUSPEND:		dbg_pm (0, "PM_SUSPEND");		if (!pm_suspended) {			pm_suspended = 1;			dbg_init (1, "MOD_INC_USE_COUNT %d", GET_USE_COUNT (THIS_MODULE));			udc_disconnect ();	// disable USB pullup if we can			udc_disable_interrupts (device);	// disable interupts			udc_disable ();	// disable UDC			dbg_pm (0, "PM_SUSPEND: finished");		}		break;#if defined(CONFIG_IRIS)	case PM_UNBLANK:#endif	case PM_RESUME:		dbg_pm (0, "PM_RESUME");		if (pm_suspended) {			// probe for device			if (udc_init ()) {				dbg_init (0, "udc_init failed");				//return -EINVAL;			}			udc_enable (device);	// enable UDC			udc_all_interrupts (device);	// enable interrupts			udc_connect ();	// enable USB pullup if we can			//udc_set_address(device->address);			//udc_reset_ep(0);			pm_suspended = 0;			dbg_init (1, "MOD_INC_USE_COUNT %d", GET_USE_COUNT (THIS_MODULE));			dbg_pm (0, "PM_RESUME: finished");		}		break;	}	return 0;}#endif#ifdef CONFIG_DPM	/* MVL-CEE */static int bi_udc_suspend(struct device *dev, u32 state, u32 level);static int bi_udc_resume(struct device *dev, u32 level);static int bi_udc_scale(struct bus_op_point *op, u32 level);static struct device_driver bi_udc_driver_ldm = {	.name		= "usb-device",	.devclass	= NULL,	.probe		= NULL,	.suspend	= bi_udc_suspend,	.resume		= bi_udc_resume,	.scale		= bi_udc_scale,	.remove		= NULL,	.constraints	= NULL,};static struct device bi_udc_device_ldm = {	.name		= "USB Device",	.bus_id		= "usbd",	.driver		= NULL,	.power_state	= DPM_POWER_ON,};static voidbi_udc_ldm_driver_register(void){#ifdef CONFIG_OMAP_INNOVATOR	extern void mpu_public_driver_register(struct device_driver *driver);	mpu_public_driver_register(&bi_udc_driver_ldm);#endif#ifdef CONFIG_ARCH_MAINSTONE	extern void pxaopb_driver_register(struct device_driver *driver);	pxaopb_driver_register(&bi_udc_driver_ldm);#endif}static voidbi_udc_ldm_device_register(void){#ifdef CONFIG_OMAP_INNOVATOR	extern void mpu_public_device_register(struct device *device);	mpu_public_device_register(&bi_udc_device_ldm);#endif#ifdef CONFIG_ARCH_MAINSTONE	extern void pxaopb_device_register(struct device *device);	pxaopb_device_register(&bi_udc_device_ldm);#endif}static voidbi_udc_ldm_driver_unregister(void){#ifdef CONFIG_OMAP_INNOVATOR	extern void mpu_public_driver_unregister(struct device_driver *driver);	mpu_public_driver_unregister(&bi_udc_driver_ldm);#endif#ifdef CONFIG_ARCH_MAINSTONE	extern void pxaopb_driver_unregister(struct device_driver *driver);	pxaopb_driver_unregister(&bi_udc_driver_ldm);#endif}static voidbi_udc_ldm_device_unregister(void){#ifdef CONFIG_OMAP_INNOVATOR	extern void mpu_public_device_unregister(struct device *device);	mpu_public_device_unregister(&bi_udc_device_ldm);#endif#ifdef CONFIG_ARCH_MAINSTONE	extern void pxaopb_device_unregister(struct device *device);	pxaopb_device_unregister(&bi_udc_device_ldm);#endif}static intbi_udc_scale(struct bus_op_point *op, u32 level){  printk("+++: bi_udc_scale\n");	/* REVISIT */	return 0;}static intbi_udc_suspend(struct device *dev, u32 state, u32 level){	struct usb_device_instance *device = device_array[0];	if (usbd_bi_dbg)	  printk("+++: bi_udc_suspend\n");		switch (level) {	case SUSPEND_POWER_DOWN:		dbg_pm (0, "SUSPEND_POWER_DOWN");		dbg_init (1, "MOD_INC_USE_COUNT %d", 			GET_USE_COUNT (THIS_MODULE));		udc_disconnect ();		/* disable USB pullup */		if (device)			udc_disable_interrupts (device);	/* disable interrupts */		udc_disable ();			/* disable UDC */		dbg_pm (0, "SUSPEND_POWER_DOWN: finished");		break;	}	return 0;}static intbi_udc_resume(struct device *dev, u32 level){	int ret = 0;	struct usb_device_instance *device = device_array[0];	if (usbd_bi_dbg)	  printk("+++: bi_udc_resume\n");		switch (level) {	case RESUME_POWER_ON:		dbg_pm (0, "RESUME_POWER_ON");		if (udc_init ()) {			dbg_init (0, "udc_init failed");		}		if (device) {			udc_enable (device);		/* enable UDC */			udc_all_interrupts (device);	/* enable interrupts */		}		udc_connect ();			/* enable USB pullup */		dbg_init (1, "MOD_INC_USE_COUNT %d", 			GET_USE_COUNT (THIS_MODULE));		dbg_pm (0, "RESUME_POWER_ON: finished");		break;	}	return ret;}#endif	/* ifdef CONFIG_DPM */#ifdef CONFIG_USBD_PROCFS/* Proc Filesystem *************************************************************************** *//* * * usbd_proc_read - implement proc file system read. * @file * @buf * @count * @pos * * Standard proc file system read function. */static ssize_t usbd_proc_read (struct file *file, char *buf, size_t count, loff_t * pos){        struct usb_device_instance *device;	unsigned long page;	int len = 0;	int index;	MOD_INC_USE_COUNT;	// get a page, max 4095 bytes of data...	if (!(page = get_free_page (GFP_KERNEL))) {		MOD_DEC_USE_COUNT;		return -ENOMEM;	}	len = 0;	index = (*pos)++;	switch (index) {        case 0:		len += sprintf ((char *) page + len, "USBD Status\n");                break;        case 1:

⌨️ 快捷键说明

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