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

📄 usb_ctl_pxa.c

📁 LUBBOCK板的BLOB
💻 C
📖 第 1 页 / 共 2 页
字号:
		return -EPERM;
	}
	/* mask everything */
	/* disable suspend/resume, reset */
	udc_set_mask_UDCCR( UDCCR_SRM | UDCCR_REM); 
	/* disable ep0, ep1, ep2 */
	UICR0 |= (UICR0_IM0 | UICR0_IM1 | UICR0_IM2) ;

	ep1_reset();
	ep2_reset();

	udc_disable();
	//if( usb_debug) printk( "%sStopped %s\n", pszMe, usbd_info.client_name );
	return 0;
}

/* Tell PXA core client is through using it */
int
pxa_usb_close( void )
{
	 if ( usbd_info.client_name == NULL ) {
		 /*
		   printk( "%s%s - no client registered\n",
				  pszMe, __FUNCTION__ );
		 */
		  return -EPERM;
	 }
	 //printk( "%s%s closed.\n", pszMe, (char*)usbd_info.client_name );
	 usbd_info.client_name = NULL;
	 return 0;
}

/* set a proc to be called when device is configured */
usb_notify_t pxa_set_configured_callback( usb_notify_t func )
{
	 usb_notify_t retval = configured_callback;
	 configured_callback = func;
	 return retval;
}

/*====================================================
 * Descriptor Manipulation.
 * Use these between open() and start() above to setup
 * the descriptors for your device.
 *
 */

/* get pointer to static default descriptor */
desc_t *
pxa_usb_get_descriptor_ptr( void ) { return &desc; }

/* optional: set a string descriptor */
int
pxa_usb_set_string_descriptor( int i, string_desc_t * p )
{
	 int retval;
	 if ( i < MAX_STRING_DESC ) {
		  string_desc_array[i] = p;
		  retval = 0;
	 } else {
		  retval = -EINVAL;
	 }
	 return retval;
}

/* optional: get a previously set string descriptor */
string_desc_t *
pxa_usb_get_string_descriptor( int i )
{
	 return ( i < MAX_STRING_DESC )
		    ? string_desc_array[i]
		    : NULL;
}

config_desc_t *
pxa_usb_get_config(int cfgval) 
{
	int i;
	desc_t * pdesc = pxa_usb_get_descriptor_ptr();
	config_desc_t *cfg = (config_desc_t*) (pdesc->cdb);

	for( i=0; i<pdesc->dev.bNumConfigurations; i++) {
		if( cfg->bConfigurationValue == cfgval ) return cfg;
		cfg = (config_desc_t*) ((unsigned char*)cfg + cfg->wTotalLength);
	}

	return NULL;
}

intf_desc_t *
pxa_usb_get_interface( config_desc_t *cfg, int idx)
{
	int i;
	intf_desc_t *intf = (intf_desc_t*) (cfg + 1);
	
	for( i=0; i < cfg->bNumInterfaces; i++) {
		if( idx == intf->bInterfaceNumber) return intf;
		intf++;
	}

	return NULL;
}


ep_desc_t *
pxa_usb_get_endpoint( intf_desc_t *intf, int idx)
{
	int i;
	ep_desc_t *ep = (ep_desc_t *) (intf+1);


	for( i=0; i< intf->bNumEndpoints; i++) {
		if( idx == (ep->bEndpointAddress & 0xF) ) return ep;
		ep++;
	}
	return NULL;
}

//////////////////////////////////////////////////////////////////////////////
// Exports to rest of driver
//////////////////////////////////////////////////////////////////////////////

/* called by the int handler here and the two endpoint files when interesting
   .."events" happen */

int
usbctl_next_state_on_event( int event )
{
	int next_state = device_state_machine[ sm_state ][ event ];
	if ( next_state != kError )
	{
		int next_device_state = sm_state_to_device_state[ next_state ];
		/*
		if( usb_debug) printk( "%s%s --> [%s] --> %s. Device in %s state.\n",
				pszMe, state_names[ sm_state ], event_names[ event ],
				state_names[ next_state ], device_state_names[ next_device_state ] );
		*/
		/*
		SerialOutputString(pszMe);
		SerialOutputString(state_names[sm_state]);
		SerialOutputString(" --> ");
		SerialOutputString(event_names[event]);
		SerialOutputString(" --> ");
		SerialOutputString(state_names[next_state]);
		SerialOutputString("device in state:");
		SerialOutputString(device_state_names[next_device_state]);
		SerialOutputString("\n");
		*/

		sm_state = next_state;
		if ( usbd_info.state != next_device_state )
		{
			if ( configured_callback != NULL
				 &&
				 next_device_state == USB_STATE_CONFIGURED
				 &&
				 usbd_info.state != USB_STATE_SUSPENDED
			   ) {
			  configured_callback();
			}
			usbd_info.state = next_device_state;

			ep1_state_change_notify( next_device_state );
			ep2_state_change_notify( next_device_state );
		}
	}
	/*
	else
		printk( "%s%s --> [%s] --> ??? is an error.\n",
				pszMe, state_names[ sm_state ], event_names[ event ] );
	*/
	return next_state;
}

//////////////////////////////////////////////////////////////////////////////
// Private Helpers
//////////////////////////////////////////////////////////////////////////////

/* setup default descriptors */

static void
initialize_descriptors(void)
{

	desc.dev.bLength               = sizeof( device_desc_t );
	desc.dev.bDescriptorType       = USB_DESC_DEVICE;
	desc.dev.bcdUSB                = 0x100; /* 1.0 */
	desc.dev.bDeviceClass          = 0xFF;	/* vendor specific */
	desc.dev.bDeviceSubClass       = 0;
	desc.dev.bDeviceProtocol       = 0;
	desc.dev.bMaxPacketSize0       = 16;	/* ep0 max fifo size */
	desc.dev.idVendor              = 0;	/* vendor ID undefined */
	desc.dev.idProduct             = 0; 	/* product */
	desc.dev.bcdDevice             = 0; 	/* vendor assigned device release num */
	desc.dev.iManufacturer         = 0;	/* index of manufacturer string */
	desc.dev.iProduct              = 0; 	/* index of product description string */
	desc.dev.iSerialNumber         = 0;	/* index of string holding product s/n */
	desc.dev.bNumConfigurations    = 1;	/* configurations we have */

	/*
	desc.b.cfg.bLength             = sizeof( config_desc_t );
	desc.b.cfg.bDescriptorType     = USB_DESC_CONFIG;
	desc.b.cfg.wTotalLength        = make_word_c( sizeof(struct cdb) );
	desc.b.cfg.bNumInterfaces      = 1;
	desc.b.cfg.bConfigurationValue = 1;
	desc.b.cfg.iConfiguration      = 0;
	desc.b.cfg.bmAttributes        = USB_CONFIG_BUSPOWERED;
	desc.b.cfg.MaxPower            = USB_POWER( 500 );

	desc.b.intf.bLength            = sizeof( intf_desc_t );
	desc.b.intf.bDescriptorType    = USB_DESC_INTERFACE;
	desc.b.intf.bInterfaceNumber   = 0; 
	desc.b.intf.bAlternateSetting  = 0;
	desc.b.intf.bNumEndpoints      = 2;
	desc.b.intf.bInterfaceClass    = 0xFF; 
	desc.b.intf.bInterfaceSubClass = 0;
	desc.b.intf.bInterfaceProtocol = 0;
	desc.b.intf.iInterface         = 0;
	*/

/*
 * FIXME...
 * The host usbnet driver expects EP1=out EP2=in. On the PXA UDC EP1=in, EP2=out
 */
	/*
	desc.b.ep1.bLength             = sizeof( ep_desc_t );
	desc.b.ep1.bDescriptorType     = USB_DESC_ENDPOINT;
	desc.b.ep1.bEndpointAddress    = USB_EP_ADDRESS( 1, USB_IN );
	desc.b.ep1.bmAttributes        = USB_EP_BULK;
	desc.b.ep1.wMaxPacketSize      = make_word_c( 64 );
	desc.b.ep1.bInterval           = 0;

	desc.b.ep2.bLength             = sizeof( ep_desc_t );
	desc.b.ep2.bDescriptorType     = USB_DESC_ENDPOINT;
	desc.b.ep2.bEndpointAddress    = USB_EP_ADDRESS( 2, USB_OUT );
	desc.b.ep2.bmAttributes        = USB_EP_BULK;
	desc.b.ep2.wMaxPacketSize      = make_word_c( 64 );
	desc.b.ep2.bInterval           = 0;
	*/

// FIXME: Add support for all endpoint...

	/* set language */
	/* See: http://www.usb.org/developers/data/USB_LANGIDs.pdf */
	sd_zero.bDescriptorType = USB_DESC_STRING;
	sd_zero.bLength         = sizeof( string_desc_t );
	sd_zero.bString[0]      = make_word_c( 0x409 ); /* American English */
	pxa_usb_set_string_descriptor( 0, &sd_zero );
}

/* soft_connect_hook()
 * Some devices have platform-specific circuitry to make USB
 * not seem to be plugged in, even when it is. This allows
 * software to control when a device 'appears' on the USB bus
 * (after Linux has booted and this driver has loaded, for
 * example). If you have such a circuit, control it here.
 */
static void
soft_connect_hook( int enable )
{
}

/* disable the UDC at the source */
static void
udc_disable(void)
{
	soft_connect_hook( 0 );
	/* clear UDC-enable */
	udc_clear_mask_UDCCR( UDCCR_UDE); 

        /* Disable clock for USB device */
        CKEN &= ~CKEN11_USB;
}


/*  enable the udc at the source */
static void
udc_enable(void)
{
        /* Enable clock for USB device */
        CKEN |= CKEN11_USB;

	/* try to clear these bits before we enable the udc */
	udc_ack_int_UDCCR( UDCCR_SUSIR);
	udc_ack_int_UDCCR( UDCCR_RSTIR);
	udc_ack_int_UDCCR( UDCCR_RESIR);

	/* set UDC-enable */
	udc_set_mask_UDCCR( UDCCR_UDE); 
	if( (UDCCR & UDCCR_UDA) == 0)
	{
		/* There's a reset on the bus,
		 * clear the interrupt bit and keep going
		 */
		SerialOutputString("reset on bus\n");
		udc_ack_int_UDCCR( UDCCR_RSTIR);
	}
	
	/* "USB test mode" to work around errata 40-42 (stepping a0, a1) 
	 * which could result in missing packets and interrupts. 
	 * Supposedly this turns off double buffering for all endpoints.
	 */
	//if( usb_debug) printk( "USB RES1=%x RES2=%x RES3=%x\n", UDC_RES1, UDC_RES2, UDC_RES3);
	/*
	SerialOutputString("  RES1=");
	SerialOutputHex(UDC_RES1);
	SerialOutputString("  RES2=");
	SerialOutputHex(UDC_RES2);
	SerialOutputString("  RES3=");
	SerialOutputHex(UDC_RES3);
	SerialOutputString("\n");
	*/


	UDC_RES1 = 0x00;
	UDC_RES2 = 0x00;
	//if( usb_debug) printk( "USB RES1=%x RES2=%x RES3=%x\n", UDC_RES1, UDC_RES2, UDC_RES3);
	/*
	SerialOutputString("  RES1=");
	SerialOutputHex(UDC_RES1);
	SerialOutputString("  RES2=");
	SerialOutputHex(UDC_RES2);
	SerialOutputString("  RES3=");
	SerialOutputHex(UDC_RES3);
	SerialOutputString("\n");
	*/
}

//////////////////////////////////////////////////////////////////////////////
// Module Initialization and Shutdown
//////////////////////////////////////////////////////////////////////////////
/*
 * usbctl_init()
 * Module load time. Allocate dma and interrupt resources. Setup /proc fs
 * entry. Leave UDC disabled.
 */
int usbctl_init( void )
{
	int retval = 0, rc;

	udc_disable();

	memset( &usbd_info, 0, sizeof( usbd_info ) );
	//printk( "PXA USB Controller Core Initialized\n");
	//SerialOutputString("PXA USB Controller Core Initialized\n");
	
	rc = pxa_usb_open("myusb");
	pxa_usb_start();

	return 0;
}

/*
 * usbctl_exit()
 * Release DMA and interrupt resources
 */
void usbctl_exit( void )
{
	//printk("Unloading PXA USB Controller\n");
	udc_disable();
}

__initlist(usbctl_init, INIT_LEVEL_INITIAL_HARDWARE);
__exitlist(usbctl_exit, INIT_LEVEL_INITIAL_HARDWARE);

⌨️ 快捷键说明

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