usb_ep1_pxa.c
来自「LUBBOCK板的BLOB」· C语言 代码 · 共 216 行
C
216 行
/*
* Generic xmit 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_send.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 *ep1_buf;
static int ep1_len;
static int ep1_remain;
static usb_callback_t ep1_callback;
static int tx_pktsize;
/* device state is changing, async */
void
ep1_state_change_notify( int new_state )
{
}
/* set feature stall executing, async */
void
ep1_stall( void )
{
UDCCS1 |= UDCCS_BI_FST;
}
static void
ep1_send_packet(void)
{
int i;
char *buf = ep1_buf + ep1_len - ep1_remain;
int out_size = tx_pktsize;
//if( usb_debug) printk( "ep1_send_packet: UICR0=%x UDCCS1=%x\n", UICR0, UDCCS1);
if( out_size > ep1_remain)
{
out_size = ep1_remain;
}
for( i=0; i<out_size; i++)
{
UDDR1 = *buf++;
}
UDCCS1 = UDCCS_BI_TPC;
if( out_size < tx_pktsize)
{
/* short packet */
UDCCS1 = UDCCS_BI_TSP;
}
ep1_remain -= out_size;
/*
if( usb_debug) printk( "ep1_send_packet: "
"UICR0=%x UDCCS1=%x send bytes=%d left=%d\n",
UICR0, UDCCS1, out_size, ep1_remain);
*/
}
static void
ep1_start(void)
{
if (!ep1_len)
return;
UICR0 &= ~UICR0_IM1;
ep1_send_packet();
}
static void
ep1_done(int flag)
{
int size = ep1_len - ep1_remain;
if (ep1_len) {
ep1_len = 0;
if (ep1_callback)
ep1_callback(flag, size);
}
}
int
ep1_init(int chn)
{
/*
int i;
desc_t * pdesc = pxa_usb_get_descriptor_ptr();
for ( i = 0; i < pdesc->ep_num; i++ ) {
if( BULK_IN1 == ( 0xF & pdesc->ep[i].bEndpointAddress) ) {
tx_pktsize = __le16_to_cpu( pdesc->ep[i].wMaxPacketSize );
}
}
*/
/* FIXME */
tx_pktsize = 64;
ep1_done(-EAGAIN);
return 0;
}
void
ep1_reset(void)
{
/*
int i;
desc_t * pdesc = pxa_usb_get_descriptor_ptr();
for ( i = 0; i < pdesc->ep_num; i++ ) {
if( BULK_IN1 == ( 0xF & pdesc->ep[i].bEndpointAddress) ) {
tx_pktsize = __le16_to_cpu( pdesc->ep[i].wMaxPacketSize );
}
}
*/
/* FIXME */
tx_pktsize = 64;
UDCCS1 &= ~UDCCS_BI_FST;
ep1_done(-EINTR);
}
void
ep1_int_hndlr(int usir0)
{
int status = UDCCS1;
if (ep1_remain != 0) {
/* more data to go */
ep1_start();
} else {
if( status & UDCCS_BI_TPC)
{
UDCCS1 = UDCCS_BI_TPC;
}
ep1_done(0);
}
}
int
ep1_send(char *buf, int len, usb_callback_t callback)
{
int i=0;
int flags;
/*
if( usb_debug) printk( "pxa_usb_send: "
"data len=%d state=%d blen=%d\n",
len, usbd_info.state, ep1_len);
*/
if (usbd_info.state != USB_STATE_CONFIGURED)
return -ENODEV;
if (ep1_len) {
SerialOutputString("busy...\n");
return -EBUSY;
}
/*
for ( i=0; i < len; i++) {
SerialOutputHex(buf[i]);
SerialOutputString(" ");
}
SerialOutputString("\n");
*/
//local_irq_save(flags);
ep1_buf = buf;
ep1_len = len;
ep1_callback = callback;
ep1_remain = len;
ep1_start();
//local_irq_restore(flags);
return 0;
}
int
ep1_xmitter_avail( void )
{
if (usbd_info.state != USB_STATE_CONFIGURED)
return -ENODEV;
if (ep1_len)
return -EBUSY;
return 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?