Re: USB from SwiftForth

From: JFong <jfong_at_ms4.hinet.net>
Date: Thu, 22 Oct 2009 14:54:31 +0800

Hi! Alan,
     You are at the same situation as I had a few months ago. The attachment is
the source of a HID driver
I wrote at that time for our product "USB2Any". It works, but maybe not perfect.
This driver can be built
under SwiftForth.

     Best Regards,
     Jach Fong

Alan Furman say:
>> From: Mike Ghan <MikeGhan_at_logix-controls.com>
>> Sent: Oct 21, 2009 7:45 PM
>> To: sftalk_at_forth.com
>> Subject: [sftalk] Re: USB from SwiftForth
>>
>> It appears an interface DLL is what you need - this might be what you're
>> looking for:
>> https://www.silabs.com/products/mcu/Pages/USBXpress.aspx
>>
>> Mike
>
>
> In order to use the USBXpress DLLs, I must program the device (C8051F320) to follow the protocol expected by USBXpress: data packet size, which endpoint for which direction, proper handling of control transfers, etc. Theoretically, USBXpress could use an existing USB class, meaning that a (partial) definition of the protocol would be publicly available, but then again it could be (and likely is) a custom Windows USB driver using a "vendor-defined" class.
>
> So how do I program the device? AN169, the USBXpress Programmer's Guide,
>
> https://www.silabs.com/Support%20Documents/TechnicalDocs/an169.pdf
>
> on page 14, first paragraph, tells us The Way You Are Supposed To Do It: "The API is provided in the form of a library file precompiled under the Keil C51 tool chain. Device firmware must be developed using the Keil Sofware C51 tool chain." There does not seem to be any C source for this package provided on the development CD that I could reverse-engineer.
>
> Next I looked at AN220,
>
> https://www.silabs.com/Support%20Documents/TechnicalDocs/an220.pdf
>
> which is about "customizing" USBXpress. But it only lets you edit vendor IDs and strings, and gives no information about the protocol.
>
> Figure 1, page 1 of AN169 shows the same Windows driver stack communicating with either an 'F32x MCU or with a CP210x USB-UART bridge chip. So it must be the same protocol. Surely, I hoped, the latter's data sheet
>
> https://www.silabs.com/Support%20Documents/TechnicalDocs/CP2101.pdf
>
> will give enough information so that instead of relying solely on the USBXpress Windows driver, one can write one's own driver.
>
> Wrong.
>
> Have I overlooked something?
>
>
> Alan Furman
>
>
>
> ----------------------------------------------------------------------
> sftalk_at_forth.com The SwiftForth programming discussion email list
> To unsubscribe, send subject "unsubscribe" to sftalk-request_at_forth.com
> For list command help, send subject "help" to sftalk-request_at_forth.com
> Message archives are located at http://www.forth.com/archive/sftalk
> ----------------------------------------------------------------------
> This list is a forum for SwiftForth users. For product support and
> bug reports, please send email to support_at_forth.com
> ----------------------------------------------------------------------
>
>

-- Attached file included as plaintext by Ecartis --
-- File: HIDOvlp.F

\ TASK _HIDTest, using OVERLAPPED read/write, Release version
EMPTY
\ REQUIRES PROTECTION
CASE-SENSITIVE
\ 1 IMPORT: MessageBeep \ For debug purpose

DECIMAL

\ KERNAL32.DLL
4 IMPORT: CreateEvent ( attrib manreset initial name -- handle )
2 IMPORT: WaitForSingleObject ( hevent timeout -- ior )
1 IMPORT: CancelIo ( hevent -- bool)
4 IMPORT: GetOverlappedResult ( hfile 'overlap 'count wait -- bool )

LIBRARY C:\WINDOWS\SYSTEM32\HID.DLL
1 IMPORT: HidD_GetHidGuid
2 IMPORT: HidD_GetAttributes
2 IMPORT: HidD_GetPreparsedData
1 IMPORT: HidD_FreePreparsedData
2 IMPORT: HidP_GetCaps
3 IMPORT: HidD_GetProductString ( hfile *Buf BufLen -- bool)
3 IMPORT: HidD_GetSerialNumberString ( hfile *Buf BufLen -- bool)

CREATE HidGuid 16 ALLOT \ GUID
: GetHidGuid ( --) HidGuid HidD_GetHidGuid DROP ;

LIBRARY C:\WINDOWS\SYSTEM32\SETUPAPI.DLL
4 IMPORT: SetupDiGetClassDevs
1 IMPORT: SetupDiDestroyDeviceInfoList
5 IMPORT: SetupDiEnumDeviceInterfaces
6 IMPORT: SetupDiGetDeviceInterfaceDetail

$02 CONSTANT DIGCF_PRESENT
$04 CONSTANT DIGCF_ALLCLASSES
$08 CONSTANT DIGCF_PROFILE
$10 CONSTANT DIGCF_DEVICEINTERFACE
VARIABLE vhDevInfo
: GetClassDevs ( --)
   HidGuid 0 0 DIGCF_PRESENT DIGCF_DEVICEINTERFACE OR SetupDiGetClassDevs vhDevInfo ! ;
: DestroyDeviceInfoList ( --f) vhDevInfo @ SetupDiDestroyDeviceInfoList ;

CREATE DevInfoData 28 ALLOT \ ULONG(4), GUID(16), DWORD(4), ULONG(4)
: EnumDeviceInterfaces ( index--f) 28 DevInfoData !
>R vhDevInfo @ 0 HidGuid R> DevInfoData SetupDiEnumDeviceInterfaces ;

VARIABLE Length VARIABLE Required
CREATE DetailData 256 ALLOT \ DWORD, TCHAR[], BYTE(00)
: TryGetDeviceInterfaceDetail ( --f)
   vhDevInfo @ DevInfoData 0 0 Length 0 SetupDiGetDeviceInterfaceDetail ;
: GetDeviceInterfaceDetail ( --f) 5 DetailData !
   vhDevInfo @ DevInfoData DetailData Length @ Required 0 SetupDiGetDeviceInterfaceDetail ;

VARIABLE hDevHandle
: GetHandle ( --) DetailData 4 +
   GENERIC_READ GENERIC_WRITE OR FILE_SHARE_READ FILE_SHARE_WRITE OR
   0 OPEN_EXISTING FILE_FLAG_OVERLAPPED 0 CreateFile hDevHandle ! ;
: fCloseHandle ( --f) hDevHandle @ CloseHandle ;
: CancelI/O ( --f) hDevHandle @ CancelIo ; \ If timeout, we need this one to cancel the IO action

CREATE HidAttributes 10 ALLOT \ ULONG, USHORT(VID), USHORT(PID), USHORT(VER)
: GetAttributes ( --f) 10 HidAttributes !
   hDevHandle @ HidAttributes HidD_GetAttributes ;
CREATE StrBufPD 256 ALLOT
: GetProductString ( --f) hDevHandle @ StrBufPD 256 HidD_GetProductString ;
CREATE StrBufSN 256 ALLOT
: GetSerialNumber ( --f) hDevHandle @ StrBufSN 256 HidD_GetSerialNumberString ;

\ Using "GetDeviceInterfaceDetail GetLastError" to get the error code
\ Using "GetDeviceInterfaceDetail 0 LAST-ERROR-ALERT" to see the error message

$10C4 CONSTANT cVID $0001 CONSTANT cPID $55AA CONSTANT cVER 0 VALUE vListIndex
: vListIndex++ ( --n) vListIndex DUP 1+ TO vListIndex ;
: IsThisDevice ( --f) HidAttributes 4 + W@ cVID = HidAttributes 6 + W@ cPID = AND
   HidAttributes 8 + W@ cVER = AND ;
: GetHIDInfoList ( --) GetHidGuid GetClassDevs ;
: FindDevice ( --rc) 0 TO vListIndex
   BEGIN vListIndex++ EnumDeviceInterfaces 0= IF 1 EXIT THEN \ No HID devices
     TryGetDeviceInterfaceDetail DROP
     GetDeviceInterfaceDetail 0= IF 2 EXIT THEN
     GetHandle hDevHandle @ -1 = NOT IF
       GetAttributes IF IsThisDevice IF 0 EXIT THEN THEN \ Keep Device_Handle open
     THEN fCloseHandle DROP
   AGAIN ;
\ : FreeHIDInfoList ( --) DestroyDeviceInfoList DROP ;

00 [IF]
CREATE PreparsedData 1024 ALLOT \ as large as possible
: GetPreparsedData ( --f)
   hDevHandle @ PreparsedData HidD_GetPreparsedData ;
: FreePreparsedData ( --f) PreparsedData HidD_FreePreparsedData ;

CREATE Capabilities 1024 ALLOT \ as large as possible
: GetCaps ( --nststus) PreparsedData Capabilities HidP_GetCaps ;
[THEN]

00 [IF]
: TRY1 ( --) \ should see a value
   GetHandle
   GetAttributes U.
   ;
: FREE-TRY1 ( --) fCloseHandle U. ;
[THEN]

CREATE OVLP 0 , 0 , 0 , 0 , 0 , \ Internal, InternalHigh, Offset, OffsetHigh, hEventObject
VARIABLE hEventObject
\ : SIGNAL ( -- ) hEventObject @ SetEvent DROP ;
: MAKE ( -- ) 0 1 1 0 CreateEvent DUP hEventObject ! OVLP 16 + ! ;
: CLOSE ( -- ) hEventObject @ CloseHandle DROP 0 hEventObject ! ;

\ The following codes is target related. It is for C8051F320-TB board running on modified HID example.
$40 CONSTANT PKGLen
PKGLen 1+ CONSTANT cInBufSize \ the byte is ReportID which was not counted in target's IN_REPORT length
VARIABLE ByteRead
CREATE 1+InBuf cInBufSize ALLOT \ BYTE ReportID, BYTE IN_REPORT[64].
: fReadFile ( --f) 0 1+InBuf C! \ Set ReportID=0
   hDevHandle @ 1+InBuf cInBufSize ByteRead OVLP ReadFile ;

PKGLen 1+ CONSTANT cOutBufSize \ the byte is ReportID which was not counted in target's OUT_REPORT length
VARIABLE ByteWritten
CREATE 1+OutBuf cOutBufSize ALLOT \ BYTE ReportID, BYTE OUT_REPORT[64].
: fWriteFile ( --f) 0 1+OutBuf C! \ Set ReportID=0
   hDevHandle @ 1+OutBuf cOutBufSize ByteWritten OVLP WriteFile ;

\ Words for checking the result
VARIABLE ByteRW
: SeeResult ( --rc) hDevHandle @ OVLP ByteRW 0 GetOverlappedResult DROP GetLastError ;
: msWAIT ( max --) hEventObject @ SWAP WaitForSingleObject ; \ Some XP has no stack value on return
\ : msWAIT ( max --) hEventObject @ SWAP WaitForSingleObject DROP ; \ but the PC(Dell 5150) has
\ If timeout, the OVLP.Internal is not 0. If OK, the OVLP.Internal is 0 and OVLP.InternalHigh is #Byte read/write
   
\ Usage: OpenU2A, ...testing.. , CloseU2A
\ After fReadFile or fWriteFile(both will return 0), the result has to be checked by using one of the following two ways:
\ 1. Using "SeeResult" to check the error-code. Check it until it is zero, or timeout it by your own.
\ 2. Using "n msWAIT" to wait. When return, check the OVLP.Internal to see if it is a timeout.
\ In either ways if a timeout occurs, you have to cancel the R/W activity by calling "CancelI/O"
0 VALUE vWaitTime
: SetMaxWaitTime ( n--rc) TO vWaitTime 0 ;
: OpenU2A ( --rc) \ 1+OutBuf cOutBufSize 0 FILL \ If error, no need to do CloseU2A
   5000 TO vWaitTime \ defalut
   GetHIDInfoList FindDevice ?DUP IF DestroyDeviceInfoList DROP EXIT THEN MAKE 0 ;
: CloseU2A ( --rc) CLOSE DestroyDeviceInfoList DROP fCloseHandle 0= ;
: ReadReport ( buf--rc) fReadFile DROP DEPTH >R vWaitTime msWAIT DEPTH R> - IF DROP THEN \ Check
   1+InBuf 1+ SWAP PKGLen CMOVE \ Move to user's buffer
   OVLP @ ?DUP IF CancelI/O DROP ELSE 0 THEN ;
\ : .InBuf ( --) CR 1+InBuf cInBufSize DUMP ;
: WriteReport ( buf--rc) 1+OutBuf 1+ PKGLen CMOVE \ Move from user's buffer
   fWriteFile DROP DEPTH >R vWaitTime msWAIT DEPTH R> - IF DROP THEN
   OVLP @ ?DUP IF CancelI/O DROP ELSE 0 THEN ;

-1 [IF] \ Release
AS OpenU2A 0 EXPORT: OpenU2A
AS CloseU2A 0 EXPORT: CloseU2A
AS ReadReport 1 EXPORT: ReadReport
AS WriteReport 1 EXPORT: WriteReport
AS SetMaxWaitTime 1 EXPORT: SetMaxWaitTime
PROGRAM F320HID.DLL
[THEN]

----------------------------------------------------------------------
sftalk_at_forth.com The SwiftForth programming discussion email list
To unsubscribe, send subject "unsubscribe" to sftalk-request_at_forth.com
For list command help, send subject "help" to sftalk-request_at_forth.com
Message archives are located at http://www.forth.com/archive/sftalk
----------------------------------------------------------------------
This list is a forum for SwiftForth users. For product support and
bug reports, please send email to support_at_forth.com
----------------------------------------------------------------------
Received on Wed Oct 21 2009 - 23:52:42 PDT


Subscribe to our e-mail list service. It's free for all SwiftForth and SwiftX users!

This archive was generated 08-Feb-2012. Archive updated nightly.