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 + -
显示快捷键?