usb joysticks

The intent of this forum is to discuss my DOS TSR programs (available at http://bretjohnson.us), how they work and don't work, new/missing features, status of updates, and anything else related to them that may need to be discussed.

Re: usb joysticks

Postby watlers world » Mon Mar 19, 2012 1:53 am

VCPI?
this sounds like what you are talking about
http://www.anonymous-insider.net/window ... 2MEMWW.pdf

heh a quote...
“Multitasking without memory management is like having a party in a closet.” – Charles Petzold.
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Re: usb joysticks

Postby Bret » Mon Mar 19, 2012 5:21 am

Here's a quote from the document:

"Windows 3.1 supports VCPI in both standard mode and 386 enhanced mode. Windows 3.0 does not support VCPI."

So, the situation isn't as dire as I thought (at least if you're not using Windows 3.0). I wonder if this is trued for Win 9x as well? Anyway, since Win 3.1 supports VCPI, you should be able to provide the simple segment:offset address and USBUHCIL will make a VCPI call to translate it into a physical address.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: usb joysticks

Postby watlers world » Mon Mar 19, 2012 6:19 am

from looking at dos stuff

"
function Linear(P: pointer): longint;
{ Return the pointer as a linear longint value }
begin
Linear := (longint(seg(P^)) shl 4) + ofs(P^)
end;
"
this is what you do with the seg/ofs then?


and so under windows...

"
GlobalDosAlloc returns a segment value and a selector value.
Uses the segment value as you would under DOS to calculate
a physical address -- shift left by 4. Program this value into the
controller's base address register, just like under DOS.
"


this creates a 24bit linear address to program the DMA controller with
(though its held in a 32bit variable)

is this the sort of physical address usbuhci can take?


from what I read....
95/98
uses a newer virtual memory manager(enhanced mode only)
so you would likly have to lock/unlock memory and VM machines

far as I know under 3.11 win16 is can load and unload VXD files
and win32 programs have to use a vxd or win16 to work with hardware
win 95 and 98 are similar (or at least win16 backwords compatable)
Last edited by watlers world on Fri Mar 23, 2012 4:01 am, edited 1 time in total.
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Re: usb joysticks

Postby Bret » Mon Mar 19, 2012 7:46 am

watlers world wrote:unction Linear(P: pointer): longint;
{ Return the pointer as a linear longint value }
begin
Linear := (longint(seg(P^)) shl 4) + ofs(P^)
end;
"
this is what you do with the seg/ofs then?


No, that is how you would provide a linear address. For a segment:offset, you simply put the segment in the high word and the offset in the low word, something like this:

SegmentOffset := (longint(seg(P^)) shl 16) + ofs(P^)

watlers world wrote:GlobalDosAlloc returns a segment value and a selector value.
Uses the segment value as you would under DOS to calculate
a physical address -- shift left by 4. Program this value into the
controller's base address register, just like under DOS.

this creates a 24bit linear address to program the DMA controller with
(though its held in a 32bit variable)

is this the sort of physical address usbuhci can take?


Yes, under the assumption that linear = physical.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: usb joysticks

Postby watlers world » Mon Mar 19, 2012 8:39 am

all right I think I have it right now

under enhanced windows VM is capable of transparently
choping up and moving memory into virtual memory(hard disk space)

when it says that linear address is physical under standard mode
it means that it is currently in ram

globaldosalloc gives segment(for dos)
and a selector (for windows)
the memory starts at offset 0

a 16bit segment as ...
a 20bit linear address (seg shl 4)
or a 32bit linear address(seg shl 16)
is still talking about the same xms/ram address

since I am not using emm386
all memory should be in ram

usbuhci is using the one segment for commands without errors
so I will stick with the seg,ofs setup

Thanks for the help.

I asume data is placed in the first few bytes of the segment

since I'm using a low speed device
should I set datasize to 8 bytes ?
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Re: usb joysticks

Postby Bret » Mon Mar 19, 2012 9:05 am

watlers world wrote:I asume data is placed in the first few bytes of the segment


It puts it wherever you tell it to (the offset value you use). Offset 0 is at the start, FFFFh at the end.

watlers world wrote:since I'm using a low speed device
should I set datasize to 8 bytes ?


It depends on the device. You will need to download the complete configuration descriptor for the device (which includes the end point descriptor(s)) to see what the end point number actually is, and to see what its maximum data size is. You'll also need to download the HID report descriptor to see what each of the bits in the downloaded data corresponds to. If you're only going to use one kind of joystick (like the Wingman) you can "hard-code" all of this and won't need to download and decode any descriptors.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: usb joysticks

Postby watlers world » Tue Mar 20, 2012 4:17 am

yes I'm just trying to get a wingman to put data in the data address

64byte structure...

I14RHostIndex=0
I14RFlags=0
I14RDeviceAddress=0
I14REndPoint=0
I14RInterfaceNum=0
I14RVendorID=046h
I14RProductID=C207h
I14RDvcClass=0
I14RDvcsubClass=0
I14RDvcProtocol=0
I14RIntfClass=3
I14RIntfsubClass=0
I14RIntfProtocol=0
I14RDataAddrOff=PtrRec(lpRealModePtr).seg
I14RDataAddrSeg=PtrRec(lpRealModePtr).ofs
I14RCallBackAddrOff:=Loword(longint(CallBackAddr))
I14RCallBackAddrSeg=Hiword(longint(CallBackAddr))
I14RUserPktID=1
I14RSetupReqType=80h
I14RSetupReq=6
I14RSetupValue=FFh
I14RSetupIndex=0
I14RSetupLength=18

RegIntfOwner
DoControl

perhaps somthing like that?
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Re: usb joysticks

Postby Bret » Wed Mar 21, 2012 5:03 am

If all you're trying to do is get some data from the joystick into a buffer, it's even simpler than that. For each different type of request, the driver only looks at fields in the 64-byte structure that matter for the particular request. E.g., every request needs an I14RRequestType and an I14RHostIndex, but the rest of the fields in the structure may or may not apply. If they don't apply for a particular request, they are ignored (it doesn't matter what's in them). To download the Device Descriptor from the joystick (probably the simplest transaction that actually involves a data transfer):

I14RRequestType = I14RRTDoControl (96h)
I14RHostIndex = Whatever the Host Index is, probably 0 in your case
I14RDeviceAddress = Whatever the Device Address is, probably 2 in your case
I14REndPPoint = 0 (Control transactions almost always go to EndPoint 0)
I14RTimeOut = Timeout value to use. If 0, it uses the default of 1 second (per retry).
I14RDataAddress = Memory Address to transfer the data to
I14RCallBackAddr = Memory address to notify when the transaction is complete.
.. If you do not want a call-back to occur, set the Segment to 0, the Offset to FFFFh, or both.
.. If the address is valid, it must end with a RETF OpCode.
I14RUserPacketID = Value that will be in the BX register when I14RCallBackAddr is called
I14RSetupReqData = 8-byte Control Setup Packet
.. I14RSetupReqType = In, Standard, Device (80h)
.. I14RSetupReq = GetDescriptor (6)
.. I14RSetupValue = 0 in low byte, DescrTypeDevice (1) in high byte
.. I14RSetupIndex = 0
.. I14RSetupLength = DeviceDescriptorSize (18)
I14RFlags:
.. I14RFlagNoRetries (10h) = Set if you do not want the driver to automatically retry the transaction if there is an error. If clear, it will retry as many as 8 times.
.. I14RFlagShortPktOK (20h) = Set if you will allow a short data packet to not be considered an error. For a Get Device Descriptor, you would not normally set this.
.. I14RFlagAddrIsPhysical (80h) = Set if I14RDataAddress is Physical, Clear if I14RDataAddress is Segment:Offset.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: usb joysticks

Postby watlers world » Thu Mar 22, 2012 5:13 am

No luck sofar...

would it look somthing like this?

"TP 5.5 test"
Attachments
wing.zip
wingman test
(3.58 KiB) Downloaded 1700 times
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Re: usb joysticks

Postby Bret » Thu Mar 22, 2012 6:07 am

Code: Select all
b64.I14RFlags:=I14RFlagShortPktOK;  Probably not a good idea -- better for flags to be 0 (unless you're using a physical data address)
b64.I14RDataSize:=18;               Is not needed, but doesn't hurt anything
b64.I14RSetupValue:=$FF;            Needs to be $0100
b64.I14RSetupIndex:=3;              Needs to be 0


The format of the Control Setup Packet (b64.I14RSetupXX) is defined in the USB specifications. Lots of boring reading if you want to do some background research.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: usb joysticks

Postby watlers world » Thu Mar 22, 2012 7:08 am

Working!
Windows 3.1x in Standard and Enhanced mode is getting data now

as you said
when Virtual Memory is enabled
I'll have to get a physical address

Thank you
that was very helpful

USBUHCI callbacks now working (they can call PM software interrupts)
Attachments
wing2.zip
working tp5.5 wingman test
(3.57 KiB) Downloaded 1716 times
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Re: usb joysticks

Postby watlers world » Thu Oct 31, 2013 12:19 pm

The laptop's disk drive that I was testing usbuhci on died.

but I found these files on one of my other computers
must have forgotten to upload them
Attachments
Wing2.zip
(8.82 KiB) Downloaded 1496 times
uhci9s.zip
(135.81 KiB) Downloaded 1510 times
uhci9.zip
(151.97 KiB) Downloaded 1499 times
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Re: usb joysticks

Postby watlers world » Sun Nov 10, 2013 1:10 pm

After a bit of work I got strings to work
perhaps I could get a bit farther using what is currently setup

(StringDescriptor:WingMan Extreme Digital 3D)

HidDescriptor:
Length=0009
DescrType=21
HID Class Release(version) Spec (BCD)=0100
HID Country Code=0021 (USA)
HID Number of Class Descriptors=0001
Type of Class Descriptor=0022 (Report)
Length of Class Descriptor=0060 (96)

function DoControl(DescrTypeHIDReport)
65535
2
65457
No Error

HidReportDescriptor:
byte0=00000101 (0005)
byte1=00000001 (0001)
byte2=00001001 (0009)
byte3=00000100 (0004)
byte4=10100001 (00A1)

A hidreport?
Now looking at those bytes...

Till now the first byte was usually...
the packet length

Now the first byte(byte 0)
contains Bits for me to decode?
(Tag(0000),Type(01),Size(01))=1 byte global item with no function?
Attachments
uhci10.zip
strings now working(bin)
(178.03 KiB) Downloaded 1491 times
uhci10s.zip
strings now working(source)
(204.35 KiB) Downloaded 1493 times
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Re: usb joysticks

Postby Bret » Mon Nov 11, 2013 4:40 am

HID descriptors are in a completely different format than "regular" USB descriptors. The first byte doesn't have anything to do with the size of the descriptor. You actually need to issue a special request to download the report descriptor, since it's not downloaded with the rest of the descriptors.

The report descriptor will tell you how many buttons and axes and hat-switches and other things the joystick has, and what each bit in the data downloaded from the joystick means.

Decipering the contents of a report descriptor is actually pretty messy and complicated, and not as straightforward as you might think it would be. You can see the contents of the report descriptor for the joystick (with descriptions of what everything means) by installing USBUHCI or USBUHCIL and USBJSTIK, plugging in the joystick, and then running "USBJSTIK /R". The code to display the contents of the report descriptor on the screen is actually contained in HIDSUPT1.COM (source code HIDSUPT1.A36), not in USBJSTIK.

USBJSTICK (and USBMOUSE and USBKEYB) all have code to download, interpret, and use the contents of the report descriptors for their various types of devices. The source code you would probably care about most is in the section called DecipherReportDescr.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: usb joysticks

Postby watlers world » Tue Nov 12, 2013 11:37 am

Perhaps somthing like this might work.

function DoControl
65535
2
65431
No Error

HidReportDescriptor:
(RTUsagePage)(0001)RptGlbUPGenericDeskTop
(RTUsage)(GenericDeskTop,$04{Joystick})
(RTCollection)=MainColApplication->

(RTUsage)(GenericDeskTop,$01{Pointing Device})
(RTCollection)=MainColPhysical->

(RTReportSize)=000A
(RTReportCount)=0002
(RTLogicalMin)=0000
(RTLogicalMax)=(00FF)(0003)
(RTPhysicalMin)=0000
(RTPhysicalMax)=(00FF)(0003)
(RTUsage)(GenericDeskTop,$30{X-axis})
(RTUsage)(GenericDeskTop,$31{Y-axis})
(RTInput)=(Data,Variable,Absolute,NoWrap,Linear,Preferred,Nonull,nonVolatile,BitField?)

(RTReportSize)=0004
(RTReportCount)=0001
(RTLogicalMax)=0007
(RTPhysicalMax)=(003B)(0001)
(RTUnit)=(0014)(0000)
(RTUsage)(GenericDeskTop,$39{Hat-Switch})
(RTInput)=(Data,Variable,Absolute,NoWrap,Linear,Preferred,Null State,nonVolatile,BitField?)

(RTReportSize)=0008
(RTLogicalMax)=(00FF)(0000)
(RTPhysicalMax)=(00FF)(0000)
(RTUsage)(GenericDeskTop,$35{Rotation around Z-axis})
(RTInput)=(Data,Variable,Absolute,NoWrap,Linear,Preferred,Nonull,nonVolatile,BitField?)

(00C0) RptTagEndCollection

(RTUnit)=0000
(RTReportSize)=0001
(RTReportCount)=0007
(RTLogicalMax)=0001
(RTPhysicalMax)=0001
(RTUsagePage)(0009)RptGlbUPButton
(RTUsageMin)=0001
(RTUsageMax)=0007
(RTInput)=(Data,Variable,Absolute,NoWrap,Linear,Preferred,Nonull,nonVolatile,BitField?)

(RTReportCount)=0001
(RTInput)=(Constant,Array,Absolute,NoWrap,Linear,Preferred,Nonull,nonVolatile,BitField?)

(RTUsagePage)(0001)RptGlbUPGenericDeskTop
(RTReportSize)=0008
(RTLogicalMax)=(00FF)(0000)
(RTPhysicalMax)=(00FF)(0000)
(RTUsage)(GenericDeskTop,$36{Slider})
(RTInput)=(Data,Variable,Absolute,NoWrap,Linear,Preferred,Nonull,nonVolatile,BitField?)

(00C0) RptTagEndCollection

Thanks for the help.
If this is ok
What was the next step?
Attachments
uhci11b.zip
exe
(183.47 KiB) Downloaded 1461 times
uhci11s.zip
source
(215.61 KiB) Downloaded 1525 times
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Re: usb joysticks

Postby Bret » Tue Nov 12, 2013 12:11 pm

Yup, that's the information you need.

The report descriptor says you have the following data. The first 10 bits are the X axis, with the values going from 0 to 3FFh (1023), followed by 10 bits for the Y axis with the same range. Then, you have a 4 bits for a hat-switch, with values going from 0 to 315 degrees. Then, you have 8 bits for a rotation-around-the-Z-axis (twisting the handle), which returns values from 0 to FFh (255). You then have 7 bits for 7 buttons, followed by a filler bit that doesn't mean anything. Finally, you have 8 bits for a slider. This is a total of 48 bits (6 bytes).

In USBJSTIK, I get that information for each joystick an put it into a common internal format that my program can understand (since each joystick is different in the order and number of bits and types of controls it has). I then have to map that information so that in the end it looks like the information coming from a standard game port (maximum 4 axes and 8 buttons). The mapping process is pretty ugly and confusing, and you can peruse the code in USBJSTIK if you're interested.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: usb joysticks

Postby watlers world » Tue Nov 12, 2013 1:35 pm

I continue to read from the source code you provide
It has made me much better at assembly.

I learn slowly.
http://win31.no-ip.org/freeware/new/watlers/oofd19.zip
Thanks for the help and advice.

The callback I have setup is deaf and dumb (Does not usge Registers.)
For your main functions this is fine because they only return when finished.

With string data I simply enter 0,0 or $FFFF,$FFFF as the callback address
and then delay some time for the download.

What should I I14RRTDo to cause the data to be placed as the String data was?
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Re: usb joysticks

Postby Bret » Wed Nov 13, 2013 3:49 am

For HID devices (joysticks, mice, keyboards), you normally set up a periodic interrupt that automatically polls the device every 10 milliseconds or so. Each device can be a little different in how often it wants things polled. The desired polling rate is one of the data bytes stored in the appropriate End Point Descriptor. In USBJSTIK, I issue an I14RRTDoInterruptPer to perform this function.

You should also be able to just poll the joystick when you want to by issuing an I14RRTDoBulk. I think most joysticks would be OK with that, though it's possible there could be some that don't like the fact that they aren't being constantly polled like they expect and may return funky data on occasion. I've never tried it, so am not sure.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: usb joysticks

Postby watlers world » Thu Nov 14, 2013 2:11 pm

I thought that a low-speed device must not have bulk endpoints.
The EndPoint descriptor for the wingman says $03
What ever works is good.

So far I cannot see any data.
If I understand right even if the data is unclear or out of order
I should be able to see some in the second data structure(I14RDataAddr).

Clearly I need to adjust what I have.

function DoInterruptPer

0097(151)= RRequestType
0001(1)= flags
0000(0)= HostIndex
0002(2)= DeviceAddress
0001(0)= EndPoint
0000(0)= ConfigValue
0000(0)= InterfaceNum
0000(0)= SearchIndex
046D(1133)= VendorID
C207(49671)= ProductID
0000(0)= DvcClass
0000(0)= DvcSubClass
0000(0)= DvcProtocol
0003(3)= IntfClass
0000(0)= IntfSubClass
0000(0)= IntfProtocol
0001(1)= RequestHandle
0014(20)= Periodicity
006E(110)= Timeout
0040(64)= DataSize
257F(9599)= DataAddrSeg
FFFF(65535)= CallBackAddrOff
FFFF(65535)= CallBackAddrSeg
0064(100)= UserPktID
0081(129)= SetupReqType
0000(0)= SetupReq
0300(768)= SetupValue
0409(1033)= SetupIndex
00FA(250)= SetupLength
0574(1396)= FrameTiming
C033(49203)= IsochSchedOff
04EB(1259)= IsochSchedSeg

when device is set to 2 you get (Invalid Device Address)
give a bad device address and get (Insufficient Resources/Memory)

I asume this means I have Insufficiently setup my 64byte structure.

Device 1 returns without errors but I would not expect data from it :P

RRTDoInterruptPer is now working,
it sends callbacks(like ticks like from a clock.)
RRTCloseHandle stops the callbacks.
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Re: usb joysticks

Postby Bret » Fri Nov 15, 2013 9:26 am

I don't know exactly how things are set up in your program, but some of the items towards the end of the list are in the wrong order. They should be:

...
Timeout
DataAddressOff
DataAddrSeg
DataSize
CallBackAddrOff
CallBackAddrSeg
UserPktID
...

Are you sure the Device Address is 2? If it got unplugged and replugged, or got reset in the software for some reason, the address may not be 2 any more. The Address is one of the first things that gets checked while processing a request, so it would catch that before it gets to an insufficient resources error. Also, you say the EndPoint should be 3, but the request shows it as EndPoint 1 (does the Device even have an EndPoint 1?).

For a DoBulk, you only need:

RequestType
Flags
HostIndex
DeviceAddress
EndPoint
TImeout
DataAddr
DataSize
CallBackAddr
UserPktID

None of the other fields matter.

Regarding Bulk vs Interrupt, you're correct that a low-speed device can't have a bulk EndPoint. From the perspective of how things actually work on the USB bus, though, there really is no difference between them. On the bus, there are effectively only three types of packets: In, Out, and Setup/Control. The difference between a DoBulk and a DoIntteruptPer request is in how the packet(s) get scheduled (whether it's just a one-time request or a request that needs to get repeated over and over again). On the bus, the Device just sees In, Out, and Control data packets addressed to an EndPoint number, but doesn't know about the schedule. The Device is just supposed to do what the host software tells it to do, when the host tells it to do it.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: usb joysticks

Postby watlers world » Fri Nov 15, 2013 2:17 pm

Well in that case I did write(); them out of order :o

Then perhaps a wingman DObulk might look somthing like this?
Attachments
wingmen.zip
do you dobulk?
(8.41 KiB) Downloaded 1482 times
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Re: usb joysticks

Postby watlers world » Sun Nov 17, 2013 7:01 am

AX and BX registers are now working on callback events.
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Re: usb joysticks

Postby Bret » Mon Nov 18, 2013 4:30 am

In your wingmen.zip, I see a few things.

First of all, in the flags, you have 81h, which means you're providing a physical data address, but then you fill the data address with segment:offset data (seg(dd) & ofs(dd)), not physical address data. The data will get stored at the wrong memory location. Your flags should just be 1 (Direction = In and Data Address = Segment:Offset), not 81h (Direction = In and Data Address = Physical).

EndPoint 0 is only for Control Requests, not actual data requests. The Wingman will have at least one other EndPoint besides 0, which will be detailed in an EndPoint Descriptor. This can be downloaded by requesting a complete configuration descriptor.

The Data Size should be 6, the number of bytes described by the HID report Descriptor. BTW, this should also match the Maximum EndPoint size shown in the EndPoint descriptor.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: usb joysticks

Postby watlers world » Mon Nov 18, 2013 11:43 am

I14RRTDoInterruptPer is now working.
Received all 6 bytes
Translated them out just as you instructed.
Swivel handle is bad.
Hat wont work right either.
X,Y,slider and All 7 buttons are ok.

Got an old dsl hub some one was throwing away.
If I plug in this full speed device it no longer tells me that the device is invalid.

Oops I did it wrong again :(
I'll try to get DObulk setup properly now.

thanks for the help
Attachments
uhci14b.zip
I14RRTDoInterruptPer setup for the wingman (as the first device)
(184.53 KiB) Downloaded 1505 times
uhci14s.zip
wingman now working
(218.62 KiB) Downloaded 1512 times
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Re: usb joysticks

Postby watlers world » Tue Nov 19, 2013 3:42 pm

I pasted the I14RRTDoInterruptPer code into a windows 3.1 driver
and to my surprise it works fine.

I have 1 joystick and one driver now :D

Looks like USBUHCI Callbacks work ok from a dll.
Attachments
USBWE3D.zip
Windows 3.1 driver for the (Wingman Extreme Digital 3D)
(228.57 KiB) Downloaded 1511 times
watlers world
 
Posts: 113
Joined: Sat Feb 04, 2012 3:08 am

Previous

Return to Programs

Who is online

Users browsing this forum: No registered users and 2 guests

cron