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

📄 usbch9.c

📁 PDIUSBD12的嵌入式软件
💻 C
📖 第 1 页 / 共 2 页
字号:
			ReplyLen = LESSER_OF( sizeof(stringDescProd), wLength );
			control_transmit( (const uchar *) &stringDescProd, ReplyLen );
			break;

		case SERIAL_NUM_STR_ID:             /* serial number string */
			ReplyLen = LESSER_OF( sizeof(stringDescSNum), wLength );
			control_transmit( (const uchar *) &stringDescSNum, ReplyLen );
			break;

		default:
			stall_ep0();
			break;
		}
	}
	else stall_ep0();
}


void get_configuration(void)
{
	uchar c = USBflags.bits.dev_configured;

	single_transmit(&c, 1);
}


void set_configuration(void)
{
	if ( ControlData.DeviceRequest.wValue == 0 )  /* put device in unconfigured state */
	{
		single_transmit(0, 0);      /* Ack */
		DISABLE_USB_IRQ;
		USBflags.bits.dev_configured = FALSE;
		RESTORE_USB_IRQ;
		unconfigure_device();
		init_rem_loc_state();
	}
	else if ( ControlData.DeviceRequest.wValue == 1 )  /* put device in configured state */
	{
		single_transmit(0, 0);      /* Ack */
		unconfigure_device();
		configure_device();
		DISABLE_USB_IRQ;
		USBflags.bits.dev_configured = TRUE;
		RESTORE_USB_IRQ;
		init_rem_loc_state();
	}
	else stall_ep0();
}


void get_interface(void)
{
	uchar txdat = 0;        /* Current (sole) interface number = 0x00 */

	single_transmit( &txdat, 1 );
}


void set_interface(void)
{
	if ( ControlData.DeviceRequest.wValue == 0 && ControlData.DeviceRequest.wIndex == 0 )
		single_transmit( 0, 0 );    /* Ack */
	else
		stall_ep0();
}


/* Called if undefined Standard Device Request is received */
void req_undefined( void )
{
	stall_ep0();
	debug_signal( BIT_14 );
}


/************************************************************************** */
/*  Utility functions req'd by USB2.0 Chapter 9 and USBTMC  class           */
/************************************************************************** */
static  ulong  usb_reconnect_time;
static  bool   usb_reconnecting = FALSE;


void stall_ep0(void)
{
	D12_SetEndpointStatus( 0, 1 );
	D12_SetEndpointStatus( 1, 1 );
}


/* Low-level D12 chip initialisation -- does not affect system IRQ status */
void USB_init(void)
{
	d12outp(D12_COMMAND, 0xF3);   /* Set Mode (detach from Vbus) */
	d12outp(D12_DATA, D12_CLOCKRUNNING|D12_NOLAZYCLOCK);
	d12outp(D12_DATA, D12_SETTOONE|D12_CLOCK_4M);

	d12outp(D12_COMMAND, 0xF4);   /* Read Int. reg (to clear power-on IRQ) */
	d12inp(D12_DATA);
	d12inp(D12_DATA);

	d12outp(D12_COMMAND, 0xFB);   /* Set DMA mode (off) */
	d12outp(D12_DATA, 0);
}


/* Initialize D12 configuration - detach from Vbus (SoftConnect = 0)  */
void disconnect_USB(void)
{
	DISABLE_USB_IRQ;
	D12_SetMode( D12_CLOCKRUNNING|D12_NOLAZYCLOCK, D12_SETTOONE|D12_CLOCK_4M );
	D12_ReadInterruptRegister();         /* Clear 'bus reset' IRQ flag */
	D12_SetDMA( 0 );
	USB_active = FALSE;
	RESTORE_USB_IRQ;

}


/* Initialize D12 configuration - attach to Vbus (SoftConnect = 1) */
void connect_USB(void)
{
	DISABLE_USB_IRQ;
	USBflags.value = 0;                  /* Clear USB state flags */
	D12_SetMode( D12_SOFTCONNECT|D12_CLOCKRUNNING|D12_NOLAZYCLOCK, D12_SETTOONE|D12_CLOCK_4M );
	D12_SetDMA( D12_ENDP4INTENABLE|D12_ENDP5INTENABLE );   /* Allow EP2 Tx and Rx interrupts */
	D12_SetAddressEnable( 0, 1 );        /* Give D12 default addr (0) and enable it */
	USB_active = TRUE;
	RESTORE_USB_IRQ;
}


/*
*   This function requires a timer of some kind, to produce a one-second (approx.) wait.
*   The timer function used here, get_tick_count(), returns the value of a 16-bit
*   free-running counter. One count (tick) is 5 milli-seconds.
*   It's probably better not to use an interrupt-driven timer for this purpose, because
*   system IRQ's may not be enabled when reconnect_USB() is called.
*/
void reconnect_USB(void)
{
	ulong  startCount = get_tick_count();

	disconnect_USB();
	while( get_tick_count() - startCount < 100 )    /* @ 100 ticks per sec */
	{
		;;;  /* Wait a second... */
	}

	connect_USB();
	usb_reconnect_time = get_tick_count();   /* Start 10 sec timeout for reconnect */
	usb_reconnecting = TRUE;                 /* see maintain_usb_connection() */
}


/*
*   This function is called frequently from the main backround loop (in main.c) to
*   ensure connection with the host is re-established following a bus reset.
*   The 'bus reset' flag (set by USB ISR) is polled; if it is set (true) and the
*   time elapsed since the last re-connect attempt is at least 4 seconds, then
*   the function will disconnect the device from the bus and set a 1 second disconnect
*   timer. When the 1 sec timer expires, the function reconnects the device to the
*   bus, allowing the host to attempt enumeration. A 4 second "hold-off" timer is
*   started on reconnection. During the hold-off interval, the function ignores any
*   further bus reset requests; it simply clears the 'bus reset' flag.
*
*   Note: This function can interfere with the host driver installation process
*   if the device is malfunctioning, e.g. not enumerating correctly.
*   It might be necessary to disable calls to the function during firmware development.
*   Enabling the function is optional, but recommended for commercial applications.
*/
void maintain_usb_connection( void )
{
	static  ulong  usb_disconnect_time;
	static  bool   usb_disconnecting = FALSE;

	if ( USBflags.bits.bus_reset )
	{
		USBflags.bits.bus_reset = FALSE;
		if ( !usb_reconnecting && !usb_disconnecting )
		{
			/* Ready to respond to bus reset req... */
			disconnect_USB();
			usb_disconnect_time = get_tick_count();     /* start 1 sec timeout */
			usb_disconnecting = TRUE;
		}
	}

	if ( usb_disconnecting )
	{
		if ( get_tick_count() - usb_disconnect_time >= 100 )  /* 1 sec elapsed */
		{
			usb_disconnecting = FALSE;
			connect_USB();
			usb_reconnect_time = get_tick_count();   /* start 4 sec hold-off */
			usb_reconnecting = TRUE;
		}
	}
	else if ( usb_reconnecting )
	{
		if ( get_tick_count() - usb_reconnect_time >= 400 )  /* 4 sec elapsed */
			usb_reconnecting = FALSE;
	}
}


void unconfigure_device(void)
{
	D12_SetEndpointEnable( 0 );          /* Disable all endpoints but EP0. */
}


void configure_device(void)
{
	D12_SetEndpointEnable( 1 );          /* Enable  all endpoints. */
}


/*
*   Function writes data into the D12 control endpoint FIFO for transmission.
*   This initiates transmission of a single-packet Control-In transfer.
*   It is assumed that the D12 EP0 TX FIFO has sufficient room to accommodate the new data.
*   The amount of data to be transmitted must be <= EP0_MAX_PACKET_SIZE.
*
*   Entry args:     (uchar *) buf = pointer to source data
*                   (ushort)  len = number of chars to write (max. EP0_MAX_PACKET_SIZE)
*   Returns:        --
*   Affects:        --
*/
void  single_transmit( uchar * buf, uchar len )
{
	if ( len <= EP0_MAX_PACKET_SIZE )
	{
		D12_WriteEndpoint( 1, buf, len );   /* EP index is 1 => Ctrl-IN (to host) */
	}
}

/*
*   Function writes 'const' data into the D12 control endpoint buffer.
*   This initiates transmission of the first (or only) packet of a Control-In transfer.
*   It is assumed that the D12 EP0 TX FIFO has sufficient room to accommodate the new data.
*   If the amount of data to be transferred (ControlData.wLength) exceeds or equals
*   EP0_MAX_PACKET_SIZE, remaining data will be transmitted by control_in_handler() on subsequent
*   EP0 TX Request interrupts. (usbisr.c)   ***Final packet must be short pkt or null pkt.***
*
*   Entry args:     (const uchar *) pSrcData = pointer to source data
*                   (ushort) len = maximum number of bytes to be transferred
*   Returns:        --
*   Affects:        ControlData.wCount, ControlData.pData, ControlData.wLength
*
*   Note:           ControlData.wLength = transfer size (bytes) as received in the last
*                   device request (Ctrl Out) pkt. ControlData.wLength is capped at len.
*
*/
void  control_transmit( const uchar * pSrcData, ushort len )
{
	ControlData.wCount = 0;                     /* Count of bytes sent so far */
	ControlData.pData = (uchar *) pSrcData;     /* Pointer to source data */

	if ( ControlData.wLength > len ) ControlData.wLength = len;

	if ( ControlData.wLength >= EP0_MAX_PACKET_SIZE )   /* More than 1 pkt to send */
	{
		D12_WriteEndpoint( 1, ControlData.pData, EP0_MAX_PACKET_SIZE );
		ControlData.wCount += EP0_MAX_PACKET_SIZE;
		DISABLE_USB_IRQ;
		USBflags.bits.control_state = USB_TRANSMIT;
		RESTORE_USB_IRQ;
	}
	else   /* Only 1 packet to send */
	{
		D12_WriteEndpoint( 1, (uchar *) pSrcData, ControlData.wLength );
		ControlData.wCount += ControlData.wLength;
		DISABLE_USB_IRQ;
		USBflags.bits.control_state = USB_IDLE;
		RESTORE_USB_IRQ;
	}
}


/*****
*   Convert Little-endian number (32 bits unsigned, stored as 4 byte array, LSB first) to
*   ulong integer (32 bits).
*
*   Entry args:     (uchar *) pSource = pointer to LSB of Little-endian number
*
*   Returns:        (ulong) value of the number stored at pSource
*   Affects:        --
*/
ulong  LittleEndianToLong( uchar * pSource )
{
	ulong  result;

	result =  (ulong) *pSource++;
	result += (ulong) *pSource++ * 256;
	result += (ulong) *pSource++ * 256;
	result += (ulong) *pSource++ * 256;

	return  result;
}


/*****
*   Convert big-endian variable (ulong integer) to Little-endian number, 32 bits,
*   stored as 4 byte array, LSB first.
*
*   Entry args:     (uchar *) pDestin = pointer to LSB of Little-endian result
*                   (ulong)  value  = number to be converted
*   Returns:        --
*   Affects:        --
*/
void  toLittleEndian( ulong value, uchar * pDestin )
{
	short  i;
	uchar * pResult = pDestin;      /* point to LSB of result */

	for ( i = 0;  i < 4;  i++ )
	{
		*pResult++ = (uchar) (value & 0xFF);
		value = value >> 8;
	}
}


/* end */

⌨️ 快捷键说明

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