📄 usb_ctl_pxa.c
字号:
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 + -