『第
10 楼』:
開發環境使用 DJGPP + FreeDOS + DPMI + DOSUSB 的驅動程式 (http://www.dosusb.net)
請參考 http://www.dosusb.net 內的論壇內容, 不同的 USB CHIP 不保證一定成功,
但我的環境下列我寫的 SOURCE CODE 是 OK 的
檔案名稱 : W6USBCOM.h
#ifndef TW6USBCOM_H
#define TW6USBCOM_H
#ifndef BYTE
#define BYTE unsigned char
#endif
#ifndef WORD
#define WORD unsigned short int
#endif
#ifdef __cplusplus
extern "C" {
#endif
void W6USBComReset(void);
WORD W6USBComDataIn(void);
int W6USBComDataOut(char *szData, int nCount);
int W6USBComGetCoding(void);
int W6USBComSetCoding(void);
int W6USBComSetState(void);
#ifdef __cplusplus
}
#endif
#endif 檔案名稱 : W6USBCOM.C
// --------------------------------------------------------------------
// 1. 需在 autoexec.bat 下啟動 USBDOS.COM
// 2. 設計文件請參考 USBDOS 的 Home Page 或 USBDOS\SAMPLES
// 3. USBDOS.COM 內定 InterruptVector = 0x65
// 4. USBDOS.COM /D 可啟動偵錯模式 (USBDOS.LOG)
// 5. urb.status bit 定義如下 :
// Bit 0: Reserved,
// Bit 1: Bitstuff error
// Bit 2: CRC/Timeout
// Bit 3: NAK
// Bit 4: Babble detected
// Bit 5: Data Buffer error
// Bit 6: Stalled
// Bit 7: Active
// Ex. 88 hex means a NAK received, since the active bit is set the data
// packet can be retried, 44 hex means a CRC/Timeout error which caused a stall.
// The device may need a reset.
// The OHCI controller returns different completion codes than the UHCI
// controller. To simplify driver development, the DOSUSB driver translates the
// OHCI completion codes to UHCI status codes. However, in the dosusb.log file
// the OHCI codes are specified.
// OHCI completion code 1 is translated to 44h, 2 to 42h, 3 to 44h, 4 to 40h,
// 5,6 and 7 to 44h, 8 to 50h, 9 to 00h, 12 to 20h, 13 to A0h and 14 to 88h.
// --------------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <signal.h>
#include "USBCom.h"
#define __PACKED__ __attribute__ ((packed))
#define C4USBInterruptVector 0x65
int gnDevAdd =1;
int gnInEndpoint =3;
int gnOutEndpoint =2;
typedef struct
{
BYTE transaction_token __PACKED__ ;
BYTE chain_end_flag __PACKED__ ;
BYTE dev_add __PACKED__ ;
BYTE end_point __PACKED__ ;
BYTE error_code __PACKED__ ;
BYTE status __PACKED__ ;
WORD transaction_flags __PACKED__ ;
WORD buffer_off __PACKED__ ;
WORD buffer_seg __PACKED__ ;
WORD buffer_length __PACKED__ ;
WORD actual_length __PACKED__ ;
WORD setup_buffer_off __PACKED__ ;
WORD setup_buffer_seg __PACKED__ ;
WORD start_frame __PACKED__ ;
WORD nr_of_packets __PACKED__ ;
BYTE int_interval __PACKED__ ;
BYTE error_count __PACKED__ ;
WORD timeout __PACKED__ ;
WORD next_urb_off __PACKED__ ;
WORD next_urb_seg __PACKED__ ;
} TURBType;
typedef struct
{
BYTE bmRequestType __PACKED__;
BYTE bRequest __PACKED__;
WORD wValue __PACKED__;
WORD wIndex __PACKED__;
WORD wLength __PACKED__;
} TDeviceRequest;
char gszUSBDataIn[1025];
//*************************************************************************************************
int main(int argc, char *argv[])
{
#ifndef ALLEGRO_MINGW32
int i, n, k;
int nInEndpoint;
char szData[128];
if(!__djgpp_nearptr_enable())
{
printf("!__djgpp_nearptr_enable()");
return(0);
}
if(W6USBComSetCoding()!=0) return(0);
if(W6USBComGetCoding()!=0) return(0);
if(W6USBComSetState()!=0) return(0);
printf("Simple TTY-Terminal at 38.400 baud - press ESC to exit\n");
nInEndpoint = gnInEndpoint;
gnInEndpoint = 1;
if( (n= W6USBComDataIn())>0 )
{
printf("Line status in hex: \n");
for(i=0;i<2;i++)
{
printf("%.2X ",gszUSBDataIn[i]);
}
}
gnInEndpoint=nInEndpoint;
for(k=0;k<30;k++)
{
// 接收內容
if((n=W6USBComDataIn())>0)
{
printf("urb.actual_length = %d\n", n);
for(i=0;i<n;i++) printf("%c", gszUSBDataIn[i]);
printf("\n");
}
szData[0] = 'A';
szData[1] = 0x00;
W6USBComDataOut(szData,1); // 送出 'A'
delay(1000);
}
#else
return(0);
#endif
}
// *************************************************************************************************
WORD W6USBComDataIn()
{
#ifndef ALLEGRO_MINGW32
__dpmi_regs regs;
TURBType urb;
// set up in request
urb.transaction_token =0x69;
urb.chain_end_flag =0;
urb.dev_add =gnDevAdd;
urb.end_point =gnInEndpoint;
urb.error_code =0;
urb.status =0;
urb.transaction_flags =0;
urb.buffer_seg =(__tb+64) >> 4; // __tb 定義在 go32.h 為一個1024K內實體記錄位址
urb.buffer_off =(__tb+64) & 0x0F;
urb.buffer_length =64;
urb.actual_length =64;
urb.setup_buffer_off =0;
urb.setup_buffer_seg =0;
urb.start_frame =0;
urb.nr_of_packets =0;
urb.int_interval =0;
urb.error_count =0;
urb.timeout =0;
urb.next_urb_off =0;
urb.next_urb_seg =0;
// 將 urb 填入 __tb
dosmemput((char *)&urb, sizeof(urb), __tb);
// registor : Flags = 0: AX = 1: BX = 2: CX = 3: DX = 4: SI = 5: DI = 6 BP = 7: DS = 8: ES = 9
regs.x.ds = __tb >> 4;
regs.x.dx = __tb & 0x0F;
__dpmi_int (C4USBInterruptVector, ®s); // call DosUHCI
// 將 __tb 回傳的資料填到 urb
dosmemget (__tb, sizeof(urb), (char *)&urb);
// invalid device address?
if (urb.error_code==1) return(0);
// transaction error?
if(urb.status > 1) return(0);
// 將 __tb 回傳的資料填到 gszUSBDataIn
if(urb.actual_length>0) dosmemget (__tb+64, urb.actual_length, gszUSBDataIn);
return(urb.actual_length);
#else
return(0);
#endif
}
// 0 : success
// 1 : Invalid device address
// 2 : transaction error?
int W6USBComDataOut(char *szData, int nCount)
{
#ifndef ALLEGRO_MINGW32
__dpmi_regs regs;
TURBType urb;
char szTmp[128];
// 把 szData 的資料指定到 __tb+64 位置
if(nCount==0) nCount=strlen(szData);
if(nCount==0) return(0);
dosmemput(szData, nCount, __tb+64);
// outputs data in buffer
// set up out request
urb.transaction_token =0xE1;
urb.chain_end_flag =0;
urb.dev_add =gnDevAdd;
urb.end_point =gnOutEndpoint;
urb.error_code =0;
urb.status =0;
urb.transaction_flags =0;
urb.buffer_seg =(__tb+64) >> 4; // __tb 定義在 go32.h 為一個1024K內實體記錄位址
urb.buffer_off =(__tb+64) & 0x0F;
urb.buffer_length =nCount;
urb.actual_length =64;
urb.setup_buffer_off =0;
urb.setup_buffer_seg =0;
urb.start_frame =0;
urb.nr_of_packets =0;
urb.int_interval =0;
urb.error_count =0;
urb.timeout =0;
urb.next_urb_off =0;
urb.next_urb_seg =0;
// 將 urb 填入 __tb
dosmemput((char *)&urb, sizeof(urb), __tb);
// registor : Flags = 0: AX = 1: BX = 2: CX = 3: DX = 4: SI = 5: DI = 6 BP = 7: DS = 8: ES = 9
regs.x.ds = __tb >> 4;
regs.x.dx = __tb & 0x0F;
__dpmi_int (C4USBInterruptVector, ®s); // call DosUHCI
// 將 __tb 回傳的資料填到 urb
dosmemget (__tb, sizeof(urb), (char *)&urb);
// invalid device address?
if (urb.error_code==1) return(urb.error_code);
// transaction error?
if(urb.status > 1) return(urb.status);
return(0);
#else
return(0);
#endif
}
// 0 : success
// 1 : Invalid device address
// 2 : transaction error?
int W6USBComGetCoding()
{
#ifndef ALLEGRO_MINGW32
__dpmi_regs regs;
TDeviceRequest device_request;
TURBType urb;
device_request.bmRequestType=0xA1;
device_request.bRequest =0x21;
device_request.wValue =0x00;
device_request.wIndex =0;
device_request.wLength =0x7;
// 把 device_request 的資料指定到 __tb+128 位置
dosmemput((char *)&device_request, sizeof(device_request), __tb+128);
// set up get Line Coding request
urb.transaction_token =0x2D;
urb.chain_end_flag =0;
urb.dev_add =gnDevAdd;
urb.end_point =0;
urb.error_code =0;
urb.status =0;
urb.transaction_flags =0;
urb.buffer_seg =(__tb+64) >> 4; // __tb 定義在 go32.h 為一個1024K內實體記錄位址
urb.buffer_off =(__tb+64) & 0x0F;
urb.buffer_length =18;
urb.actual_length =64;
urb.setup_buffer_seg =(__tb+128) >> 4; // device_request segment
urb.setup_buffer_off =(__tb+128) & 0x0F; // device_request offset
urb.start_frame =0;
urb.nr_of_packets =0;
urb.int_interval =0;
urb.error_count =0;
urb.timeout =0;
urb.next_urb_seg =0;
urb.next_urb_off =0;
// 將 urb 填入 __tb
dosmemput((char *)&urb, sizeof(urb), __tb);
// registor : Flags = 0: AX = 1: BX = 2: CX = 3: DX = 4: SI = 5: DI = 6 BP = 7: DS = 8: ES = 9
regs.x.ds = __tb >> 4;
regs.x.dx = __tb & 0x0F;
__dpmi_int (C4USBInterruptVector, ®s); // call DosUHCI
// 將 __tb 回傳的資料填到 urb
dosmemget (__tb, sizeof(urb), (char *)&urb);
// invalid device address?
if (urb.error_code==1) return(urb.error_code);
// transaction error?
if(urb.status > 1) return(urb.status);
return(0);
#else
return(0);
#endif
}
// 0 : success
// 1 : Invalid device address
// 2 : transaction error?
int W6USBComSetCoding()
{
#ifndef ALLEGRO_MINGW32
__dpmi_regs regs;
int nInEndpoint;
int nOutEndpoint;
char szData[128];
int nDataLen;
TDeviceRequest device_request;
TURBType urb;
device_request.bmRequestType=0x21;
device_request.bRequest =0x20;
device_request.wValue =0x00;
device_request.wIndex =0;
device_request.wLength =0x7;
// 把 device_request 的資料指定到 __tb+128 位置
dosmemput((char *)&device_request, sizeof(device_request), __tb+128);
// set up get Line Coding request
urb.transaction_token =0x2D;
urb.chain_end_flag =0;
urb.dev_add =gnDevAdd;
urb.end_point =0;
urb.error_code =0;
urb.status =0;
urb.transaction_flags =0;
urb.buffer_seg =0; //varseg(buffer)
urb.buffer_off =0; //varptr(buffer)
urb.buffer_length =0;
urb.actual_length =0;
urb.setup_buffer_seg =(__tb+128) >> 4; // device_request segment
urb.setup_buffer_off =(__tb+128) & 0x0F; // device_request offset
urb.start_frame =0;
urb.nr_of_packets =0;
urb.int_interval =0;
urb.error_count =0;
urb.timeout =0;
urb.next_urb_seg =0;
urb.next_urb_off =0;
// 將 urb 填入 __tb
dosmemput((char *)&urb, sizeof(urb), __tb);
// registor : Flags = 0: AX = 1: BX = 2: CX = 3: DX = 4: SI = 5: DI = 6 BP = 7: DS = 8: ES = 9
regs.x.ds = __tb >> 4;
regs.x.dx = __tb & 0x0F;
__dpmi_int (C4USBInterruptVector, ®s); // call DosUHCI
// 將 __tb 回傳的資料填到 urb
dosmemget (__tb, sizeof(urb), (char *)&urb);
// invalid device address?
if (urb.error_code==1) return(urb.error_code);
// transaction error?
if(urb.status > 1) return(urb.status);
// now send line coding structure - 38400 baud 8-N-1
nInEndpoint = gnInEndpoint;
nOutEndpoint= gnOutEndpoint;
// 0x1C200 =115200
// 0xE100 =57600
// 0x9600 =38400
// 0x4B00 =19200
// 0x2580 =9600
// 0x12C0 =4800
// 0x0960 =2400
// 0x04B0 =1200
// --> chr$(0x00)+chr$(0x96) = 0x9600 (little endian) = 38400 baud
// --> chr$(8) = 8bit
szData[0] = 0x00;
szData[1] = 0x96;
szData[2] = 0x00;
szData[3] = 0x00;
szData[4] = 0x00;
szData[5] = 0x00;
szData[6] = 0x08;
nDataLen = 7;
gnOutEndpoint = 0;
W6USBComDataOut(szData, nDataLen);
gnInEndpoint = 0;
W6USBComDataIn();
gnInEndpoint = nInEndpoint;
gnOutEndpoint = nOutEndpoint;
return(0);
#else
return(0);
#endif
}
// 0 : success
// 1 : Invalid device address
// 2 : transaction error?
int W6USBComSetState()
{
#ifndef ALLEGRO_MINGW32
__dpmi_regs regs;
TDeviceRequest device_request;
TURBType urb;
device_request.bmRequestType=0x21;
device_request.bRequest =0x22;
device_request.wValue =0x03;
device_request.wIndex =0;
device_request.wLength =0x00
// 把 device_request 的資料指定到 __tb+128 位置
dosmemput((char *)&device_request, sizeof(device_request), __tb+128);
// set up request
urb.transaction_token =0x2D;
urb.chain_end_flag =0;
urb.dev_add =gnDevAdd;
urb.end_point =0;
urb.error_code =0;
urb.status =0;
urb.transaction_flags =0;
urb.buffer_seg =(__tb+64) >> 4;
urb.buffer_off =(__tb+64) & 0x0F;
urb.buffer_length =0;
urb.actual_length =0;
urb.setup_buffer_seg =(__tb+128) >> 4; // device_request segment
urb.setup_buffer_off =(__tb+128) & 0x0F; // device_request offset
urb.start_frame =0;
urb.nr_of_packets =0;
urb.int_interval =0;
urb.error_count =0;
urb.timeout =0;
urb.next_urb_seg =0;
urb.next_urb_off =0;
// 將 urb 填入 __tb
dosmemput((char *)&urb, sizeof(urb), __tb);
// registor : Flags = 0: AX = 1: BX = 2: CX = 3: DX = 4: SI = 5: DI = 6 BP = 7: DS = 8: ES = 9
regs.x.ds = __tb >> 4;
regs.x.dx = __tb & 0x0F;
__dpmi_int (C4USBInterruptVector, ®s); // call DosUHCI
// 將 __tb 回傳的資料填到 urb
dosmemget (__tb, sizeof(urb), (char *)&urb);
// invalid device address?
if (urb.error_code==1) return(urb.error_code);
// transaction error?
if(urb.status > 1) return(urb.status);
// success
return(0);
#else
return(0);
#endif
}
void W6USBComReset()
{
#ifndef ALLEGRO_MINGW32
__dpmi_regs regs;
TURBType urb;
// set up request
urb.transaction_token =0xFF; // 0xFF 為 Reset token (參考 USBDOS.htm)
urb.chain_end_flag =0;
urb.dev_add =gnDevAdd; // 0 : 表全部
urb.end_point =0;
urb.error_code =0;
urb.status =0;
urb.transaction_flags =0;
urb.buffer_seg =0;
urb.buffer_off =0;
urb.buffer_length =0;
urb.actual_length =0;
urb.setup_buffer_seg =0;
urb.setup_buffer_off =0;
urb.start_frame =0;
urb.nr_of_packets =0;
urb.int_interval =0;
urb.error_count =0;
urb.timeout =0;
urb.next_urb_seg =0;
urb.next_urb_off =0;
// 將 urb 填入 __tb
dosmemput((char *)&urb, sizeof(urb), __tb);
// registor : Flags = 0: AX = 1: BX = 2: CX = 3: DX = 4: SI = 5: DI = 6 BP = 7: DS = 8: ES = 9
regs.x.ax = 1; // 1 : Reset command (USBDOS.HTM)
regs.x.ds = __tb >> 4;
regs.x.dx = __tb & 0x0F;
__dpmi_int (C4USBInterruptVector, ®s); // call DosUHCI
#endif
}
int W6USBComDeviceDescriptor()
{
#ifndef ALLEGRO_MINGW32
__dpmi_regs regs;
TDeviceRequest device_request;
TURBType urb;
device_request.bmRequestType = 0x80;
device_request.bRequest = 6;
device_request.wValue = 0x100;
device_request.wIndex = 0;
device_request.wLength = 8;
// 把 device_request 的資料指定到 __tb+128 位置
dosmemput((char *)&device_request, sizeof(device_request), __tb+128);
// set up request
urb.transaction_token =0x2D;
urb.chain_end_flag =0;
urb.dev_add =gnDevAdd;
urb.end_point =0;
urb.error_code =0;
urb.status =0;
urb.transaction_flags =0;
urb.buffer_seg =(__tb+64) >> 4;
urb.buffer_off =(__tb+64) & 0x0F;
urb.buffer_length =8;
urb.actual_length =8;
urb.setup_buffer_seg =(__tb+128) >> 4; // device_request segment
urb.setup_buffer_off =(__tb+128) & 0x0F; // device_request offset
urb.start_frame =0;
urb.nr_of_packets =0;
urb.int_interval =0;
urb.error_count =0;
urb.timeout =0;
urb.next_urb_seg =0;
urb.next_urb_off =0;
// 將 urb 填入 __tb
dosmemput((char *)&urb, sizeof(urb), __tb);
// registor : Flags = 0: AX = 1: BX = 2: CX = 3: DX = 4: SI = 5: DI = 6 BP = 7: DS = 8: ES = 9
regs.x.ds = __tb >> 4;
regs.x.dx = __tb & 0x0F;
__dpmi_int (C4USBInterruptVector, ®s); // call DosUHCI
// 將 __tb 回傳的資料填到 urb
dosmemget (__tb, sizeof(urb), (char *)&urb);
// invalid device address?
if (urb.error_code==1) return(urb.error_code);
// transaction error?
if(urb.status > 1) return(urb.status);
// 將 __tb 回傳的資料填到 gszUSBDataIn
if(urb.actual_length>0) dosmemget (__tb+64, urb.actual_length, gszUSBDataIn);
// 會回應 8 個 BYTES
printf("\n\nDevice Descriptor:");
printf("\nLength: %d", gszUSBDataIn[0]);
printf("\nDescriptor type: %d", gszUSBDataIn[1]);
printf("\nUSB specification nr.: %02X%02X hex", gszUSBDataIn[3],gszUSBDataIn[2]);
printf("\nClass code: %d", gszUSBDataIn[4]);
printf("\nSubclass code: %d", gszUSBDataIn[5]);
printf("\nProtocol code: %d", gszUSBDataIn[6]);
printf("\nMax Packet size: %d\n", gszUSBDataIn[7]);
// success
return(0);
#else
return(0);
#endif
}
|