usb_ep2_pxa.c
来自「LUBBOCK板的BLOB」· C语言 代码 · 共 183 行
C
183 行
/*
* Generic receive layer for the PXA USB client function
*
* This code was loosely inspired by the original version which was
* Copyright (c) Compaq Computer Corporation, 1998-1999
* Copyright (c) 2001 by Nicolas Pitre
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 02-May-2002
* Frank Becker (Intrinsyc) - derived from sa1100 usb_recv.c
*
* TODO: Add support for DMA.
*
*/
#ifdef HAVE_CONFIG_H
# include <blob/config.h>
#endif
#include <blob/arch.h>
#include <linux/errno.h>
#include "pxa_usb.h"
#include "usb_ctl_pxa.h"
#if DEBUG
static unsigned int usb_debug = DEBUG;
#else
#define usb_debug 0 /* gcc will remove all the debug code for us */
#endif
static char *ep2_buf;
static int ep2_len;
static int ep2_remain;
static usb_callback_t ep2_callback;
static int rx_pktsize;
static void
ep2_start(void)
{
/* disable DMA, RPC & SST should not be cleared */
UDCCS2 &= ~( UDCCS_BO_DME | UDCCS_BO_RPC | UDCCS_BO_SST );
/* enable interrupts for endpoint 2 (bulk out) */
UICR0 &= ~UICR0_IM2;
}
static void
ep2_done(int flag)
{
int size = ep2_len - ep2_remain;
if (!ep2_len)
return;
//SerialOutputHex("done\n");
ep2_len = 0;
if (ep2_callback) {
ep2_callback(flag, size);
}
}
void
ep2_state_change_notify( int new_state )
{
}
void
ep2_stall( void )
{
/* SET_FEATURE force stall at UDC */
UDCCS2 |= UDCCS_BO_FST;
}
int
ep2_init(int chn)
{
/*
int i;
desc_t * pdesc = pxa_usb_get_descriptor_ptr();
for ( i = 0; i < pdesc->ep_num; i++ ) {
if( BULK_OUT1 == ( 0xF & pdesc->ep[i].bEndpointAddress) ) {
rx_pktsize = __le16_to_cpu( pdesc->ep[i].wMaxPacketSize );
}
}
*/
/* FIXME */
rx_pktsize = 64;
ep2_done(-EAGAIN);
return 0;
}
void
ep2_reset(void)
{
/*
int i;
desc_t * pdesc = pxa_usb_get_descriptor_ptr();
for ( i = 0; i < pdesc->ep_num; i++ ) {
if( BULK_OUT1 == ( 0xF & pdesc->ep[i].bEndpointAddress) ) {
rx_pktsize = __le16_to_cpu( pdesc->ep[i].wMaxPacketSize );
}
}
*/
/* FIXME */
rx_pktsize = 64;
UDCCS2 &= ~UDCCS_BO_FST;
ep2_done(-EINTR);
}
void
ep2_int_hndlr(int udcsr)
{
int status = UDCCS2;
//if( usb_debug) printk("ep2_int_hndlr: UDCCS2=%x\n", status);
if( (status & (UDCCS_BO_RNE | UDCCS_BO_RSP)) == UDCCS_BO_RSP)
{
/* zero-length packet */
}
if( status & UDCCS_BO_RNE)
{
int len;
int i;
char *buf = ep2_buf + ep2_len - ep2_remain;
/* bytes in FIFO */
len = (UBCR2 & 0xff) +1;
/*
if( usb_debug) printk("usb_recv: "
"len=%d out1_len=%d out1_remain=%d\n",
len,ep2_len,ep2_remain);
*/
if( len > ep2_remain)
{
/* FIXME: if this happens, we need a temporary overflow buffer */
//printk("usb_recv: Buffer overwrite warning...\n");
len = ep2_remain;
}
/* read data out of fifo */
for( i=0; i<len; i++)
{
*buf++ = UDDR2 & 0xff;
}
ep2_remain -= len;
ep2_done((len) ? 0 : -EPIPE);
}
/* ack RPC - FIXME: '|=' we may ack SST here, too */
UDCCS2 |= UDCCS_BO_RPC;
return;
}
int
ep2_recv(char *buf, int len, usb_callback_t callback)
{
int flags;
if (ep2_len)
return -EBUSY;
ep2_buf = buf;
ep2_len = len;
ep2_callback = callback;
ep2_remain = len;
ep2_start();
return 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?