www.pudn.com > usbhost_source.rar > SL811HST.C
/**
* sl811.c
* USBホストチップドライバ
* サイプレスSL811HS
*
* Copyright (c)2004 Junichi Tomaru
*/
#include "h8hst.h"
#define USB_ACK 1
#define USB_NAK 2
#define USB_STALL 4
/**
* 指定レジスタのデータ読む
*/
byte sl_read( char addr )
{
SL811ADDR = addr; /* アドレスセット */
return SL811DATA; /* データ読み出し */
}
/**
* 指定レジスタにデータ書く
*/
void sl_write( char addr, byte data )
{
SL811ADDR = addr; /* アドレスセット */
SL811DATA = data; /* データ書き込み */
}
/**
* 指定アドレスより連続データ読む
* アドレスはIC側でオートインクリメント
*/
void sl_burstread( char addr, char *buf, int size )
{
int i;
if( size <= 0 ){
return;
}
SL811ADDR = addr; /* 先頭アドレスセット */
for( i = 0; i < size; i++ ){
*( buf + i ) = SL811DATA;
}
}
/**
* 指定アドレスより連続データ書く
* アドレスはIC側でオートインクリメント
*/
void sl_burstwrite( char addr, char *buf, int size )
{
int i;
if( size <= 0 ){
return;
}
SL811ADDR = addr; /* 先頭アドレスセット */
for( i = 0; i < size; i++ ){ /* データの書き込み */
SL811DATA = *( buf + i );
}
}
/**
* SL811HS初期化
*/
void sl_init( void )
{
usbspeed = NOSPEED;
P9DR &= 0xef;
wait10us( ); /* USBチップリセットパルス */
P9DR |= 0x10;
waitms( 1 );
sl_write( SL_CTRLREG2, 0xae ); /* マスタモード,極性切り替えなし+カウンタ2EH */
}
/**
* SETUPパケット書き込み
* ret:ACK/NAK/STALL
*/
int send_setup( char *data )
{
byte sts, ret;
sl_burstwrite( 0x10, data, 8 ); /* データ転送 */
sl_write( SL_BASEADDRA, 0x10 ); /* 転送開始アドレス */
sl_write( SL_BASELENA, 8 ); /* データ長さ */
sl_write( SL_DEVADDRA, info.addr ); /* 通信相手のデバイスアドレス */
sl_write( SL_PIDDEVEPA, PID_SETUP + 0 );/* セットアップパケット */
sl_write( SL_HOSTCTRLA, ARM + ENABLE + DIRECTION ); /* データ0で送信 */
wait100us( );
wait100us( );
while(( sl_read( SL_INTSTATUS ) & INT_USBADONE ) == 0 ){ /* 送信終了待ち */
}
sts = sl_read( SL_USBSTSA );
ret = 0;
if(( sts & ACK ) == ACK ){
ret |= USB_ACK;
}
if(( sts & NAK ) == NAK ){
ret |= USB_NAK;
}
if(( sts & STALL ) == STALL ){
ret |= USB_STALL;
}
return ret;
}
/**
* SL811HSにデータ書き込む
*/
int sl_writedata( char *data, int size )
{
byte sts, tgl, ret;
if( size < 2 ){
return 0;
}
sl_burstwrite( 0x10, data + 2, size - 2 );
sl_write( SL_BASEADDRA, 0x10 );
sl_write( SL_BASELENA, size - 2 );
sl_write( SL_DEVADDRA, info.addr );
sl_write( SL_PIDDEVEPA, PID_OUT | info.txep );
tgl = ARM + ENABLE + DIRECTION;
if( info.tgl == 1 ){
tgl += DATATGL;
}
sl_write( SL_HOSTCTRLA, tgl );
wait100us( );
wait100us( );
while(( sl_read( SL_INTSTATUS ) & INT_USBADONE ) == 0 ){ /* 送信完了待ち */
}
sts = sl_read( SL_USBSTSA );
ret = 0;
if(( sts & ACK ) == ACK ){
ret |= USB_ACK;
}
if(( sts & NAK ) == NAK ){
ret |= USB_NAK;
}
if(( sts & STALL ) == STALL ){
ret |= USB_STALL;
}
return ret;
}
/**
* SL811HSよりデータ読み出す
*/
int sl_readdata( char *data, int size )
{
byte sts, tgl, ret;
int i;
if( size < 0 ){
return 0;
}
sl_write( SL_BASEADDRA, 0x10 );
sl_write( SL_BASELENA, size );
sl_write( SL_DEVADDRA, info.addr ); /* 対象デバイスアドレス */
sl_write( SL_PIDDEVEPA, PID_IN + info.txep ); /* INパケット */
tgl = ARM + ENABLE;
if( info.tgl == 1 ){
tgl += DATATGL;
}
for( i = 0; i < 200; i++ ){
sl_write( SL_HOSTCTRLA, tgl );
wait100us( );
wait100us( );
while(( sl_read( SL_INTSTATUS ) & INT_USBADONE ) == 0 ){ /* 送信終了待ち */
}
sts = sl_read( SL_USBSTSA );
if(( sts & NAK ) == 0 ){ /* NAKでなければ抜ける */
break;
}
}
ret = 0;
if(( sts & ACK ) == ACK ){
sl_burstread( 0x10, data, size );
ret |= USB_ACK;
}
if(( sts & NAK ) == NAK ){
ret |= USB_NAK;
}
if(( sts & STALL ) == STALL ){
ret |= USB_STALL;
}
return ret;
}
/**
* デバイスチェック
*/
bool checkdevice( void )
{
byte sts;
bool ret;
sl_write( SL_INTSTATUS, 0xff ); /* すべての割り込みビットクリア */
sts = sl_read( SL_INTSTATUS );
if(( sts & 0x40 ) == 0x40 ){ /* ビットが立っているとデバイスなし */
return FALSE;
}
else{
if(( sts & 0x80 ) == 0x80 ){ /* フルスピード */
usbspeed = FULLSPEED;
dispmessage( 7 );
}
else{
usbspeed = LOWSPEED;
dispmessage( 8 );
}
}
return TRUE;
}
/**
* デバイス検出→プラグ&プレイ
*/
bool plugnplay( void )
{
byte sts, tp;
byte buf[10];
char i, tmp[4];
const char getdesc[8] = {
DEV2HOST + TYPESTD + RXDEVICE, /* bmRequestType */
GET_DESCRIPTOR, /* bRequest */
0, DEVICE, /* wValue */
0, 0, /* wIndex */
8, 0 /* Data */
};
const char setaddr[8] = {
HOST2DEV + TYPESTD + RXDEVICE, /* bmRequestType */
SET_ADDRESS, /* bRequest */
2, 0, /* wValue */
0, 0, /* wIndex */
0, 0 /* Data */
};
waitms( 100 ); /* デバイス発見→100msディレイ */
info.addr = info.txep = info.rxep = 0;
info.tgl = 1;
sl_write( SL_CTRLREG2, 0xae ); /* マスタモード,極性切り替えなし+カウンタ2EH */
sl_write( SL_SOFCNTLOW, 0xe0 );
sl_write( SL_CTRLREG1, 0x8 ); /* バスリセット */
waitms( 20 ); /* MIN10ms */
if( usbspeed == FULLSPEED ){ /* フルスピード */
sl_write( SL_CTRLREG2, 0xae ); /* データ反転なし */
sl_write( SL_CTRLREG1, 0x1 ); /* ほんとは5? */
}
else{ /* ロースピード */
sl_write( SL_CTRLREG2, 0xee ); /* データ反転あり */
sl_write( SL_CTRLREG1, 0x21 );
}
sl_write( SL_PIDDEVEPA, 0x50 );
sl_write( SL_DEVADDRA, 0x00 ); /* 相手デバイスは0 *//* 1でない? */
sl_write( SL_IER, INT_USBADONE + INT_USBBDONE + INT_SOFTIM + INT_INSREM );/* 割り込みセット */
sl_write( SL_HOSTCTRLA, 1 ); /* SOFイネーブル */
waitms( 30 );
sl_write( SL_INTSTATUS, 0xff );
if(( send_setup( (char *)getdesc ) & USB_ACK ) == 0 ){ /* デバイスディスクリプタ */
return FALSE;
}
if(( sl_readdata( buf, 8 ) & USB_ACK ) == 0 ){ /* デバイスディスクリプタ受信 */
return FALSE;
}
devdesc.length = buf[0];
devdesc.type = buf[1];
devdesc.usbver = (((int)buf[3] << 8 ) & 0xff00 );
devdesc.usbver |= ( (int)buf[2] & 0x00ff );
devdesc.class = buf[4];
devdesc.subclass = buf[5];
devdesc.protocol = buf[6];
devdesc.maxsize = buf[7];
/**/ lcdlocate( 12, 0 );
/**/ lcdputch( 'v' );
/**/ lcdputch( buf[3] + 0x30 );
/**/ lcdputch( '.' );
/**/ lcdputch( ((( buf[2] >> 4 ) & 0xf ) + 0x30 ));
/**/ for( i = 0; i < 8; i++ ){
/**/ lcdprint( i*2, 1, uctoahz( buf[i], tmp ) );
/**/ }
if(( send_setup( (char *)setaddr ) & USB_ACK ) == 0 ){ /* セットアドレス */
return FALSE;
}
info.addr = 2;
return TRUE;
}
/* end of sl811hst.c */