USB I/O

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.

USB I/O

Postby Dinosaur » Thu Jul 09, 2009 11:47 am

Hi Bret

This post is perhaps off-topic BUT,
We use a lot of custom made I/O boards that are getting more expensive every day.
The links below show usb interface boards for Mouse/joystick etc.
http://www.u-hid.com/index.php?option=c ... e&Itemid=1

This link is the one I intend to use for the Joystick.
http://www.u-hid.com/index.php?option=c ... &Itemid=19

What is the difficulty in coming up with a driver that would give me access from within my
FreeBasic program to the i/o bits. The top link has 50 programmable pins (preset them in Windows)

Basically I would think that the device driver would supply 8 bit bytes that represent the status of the bits.

I dont expect this for free.

Regards
Dinosaur
 
Posts: 70
Joined: Wed Jul 01, 2009 5:54 pm
Location: Salt Lake City USA

Re: USB I/O

Postby Bret » Thu Jul 09, 2009 1:37 pm

Let me make sure I understand what you're trying to accomplish.

You want to build your own joystick, and want to use one of these devices to provide the USB interface to communicate the joystick axes/button data with the computer. You also want to be able to configure the device from DOS/FreeBASIC instead of having to use the Windows program that they provide. Is that correct?

It looks like the only external interface to the Device that could be used for configuration is the USB connector. This means that there must be some kind of special/proprietary USB Device/Interface that is set up to configure the device, along with the other USB Device/Interfaces that appear for the joystick/keyboard/mouse that the device is trying to emulate. Have you actually got one of these devices and downloaded the USB descriptors to see what they look like? I think that would be the first step, since their "technical manual" doesn't address that aspect of things at all -- it just talks about how to use their Windows program.

I'd guess that what gets downloaded is a little more complicated than a simple bit-map, since each pin can correspond to anything from a simple button to a 12-bit analog-to-digital voltage measurement. I'm guessing this would be very complicated and time consuming to figure out, since it's unlikely that they will provide you that level of detail. I suspect you'll need to figure it out with some reverse-engineering (which is usually very time-consuming and expensive), but it's hard to say for sure. The next step would be to purchase one of the devices to see what it does, and ask the company what information they will provide.

There are a couple of legitimate reasons I could see for wanting to bypass their Windows program and build your own. The first would be if you're wanting to be able to re-configure the device in the field, either because it loses its configuration or you just want to change/upgrade something. Since the computer uses DOS instead of Windows, that would be impossible to do without a second computer. The DOS program to re-configure the device could just be some kind of batch process that the user could run (even with AUTOEXEC,BAT), and wouldn't even necessarily need to be (and probably shouldn't be) a full-featured program.

The second reason I could see for wanting to bypass their program would be that you need to re-program the device "on the fly" while your application is running. I'm guessing it would probably be easier to simply respond to the joystick inputs differently at different times with your program, rather than trying to change how the joystick itself works. But, I'm not sure exactly what you're trying to accomplish.

Am I reading too much into this, or did this help you at all?
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: USB I/O

Postby Dinosaur » Thu Jul 09, 2009 3:37 pm

Hi Bret

Sorry for the confusion
I have two separate requirements.

1.Joystick.
Industrial grade joysticks (or Thumb sticks) with a single button, are generally only sold as Analog devices.
This means you have to add your own USB interface. The supplier I deal with has done this
in the past. According to the info, If I connect the analog stick to the U-Hid-Nano, then with a
Windows computer configure the Nano to read the joystick.
Now plug the Nano into the Dos usb port, and again according to the info, it should be recognised
as a standard Mouse or Joystick. I have purchased the Nano, and will test it when it gets here.

2.USB I/O
There is now a plethora of usb i/o boards available on the internet. From cheap $30 to $200.
All of these are designed for Windows. Some are plug & play, others need special drivers.
Considering your experience with usb, is it that difficult?
For example, you are reading the many buttons from the joystick, how are these passed to the user program.?
I'd guess that what gets downloaded is a little more complicated than a simple bit-map, since each pin can correspond to anything from a simple button to a 12-bit analog-to-digital voltage measurement.
I suspect that they are using a cpld , which is programmed to redirect the input pins to the various logic blocks. These logic blocks are set by the windows program. I do this currently with our own i/o boards.
I guess the best way to help you decide, is to dump the usb descriptors and try and compare that to the setup.
Alternately, I doubt if the manufacturers would supply Dos drivers.

Will keep browsing and keep you informed.

REgards
Dinosaur
 
Posts: 70
Joined: Wed Jul 01, 2009 5:54 pm
Location: Salt Lake City USA

Re: USB I/O

Postby Bret » Thu Jul 09, 2009 6:30 pm

I don't think there will be a problem with the joystick and USBJSTIK, as long as the Nano provides a relatively standard HID report descriptor. One issue to keep in mind, though is that a mouse is IRQ driven (essentially self-reporting), while a joystick must be polled. My JOYKEYS program periodically polls the joystick (in the background), and turns the joystick actions into keystrokes which essentially makes the joystick self-reporting, similar to a mouse. I'm not sure how your FreeBasic application works -- if you need to periodically poll for the mouse status or if it has some sort of mechanism to automatically inform you when the mouse has done something it thinks you should care about. You may also be able to program the Nano so that the joystick actually looks like a mouse to the computer. Even before you get the Nano, you may want to experiment with a regular joystick or gamepad and see how your FreeBasic application reacts.

If the I/O ports are just set up as a bit array, it should be relatively easy to get the data (famous last words). In fact, you should be able to talk directly to the I/O device at the USB level by communicating between your FreeBasic application and the BIOS-level API provided by USBUHCI{L}. The standard device drivers (USBJSTIK, USBMOUSE, etc.) are a sort of "middleware" which makes a DOS program think it's talking to legacy hardware (PS2 mice and keyboards, game port joysticks, parallel printers, etc.). They simply emulate the interfaces that legacy DOS programs already understand. In your case, there is no legacy interface to emulate, and there shouldn't be a need for a special API (although one could certainly be developed). The API that's built into USBUHCI{L} is designed with your kind of application in mind. Like you stated, you'll need to download some descriptors to see what they look like, and ask the vendor for any additional information they might be willing to provide. ALL devices need drivers -- plug-and-play just means the drivers were already included on the Windows installation disk. Any device that claims it doesn't need a driver is lying. A device that claims it is plug-and-play with Windows won't necessarily be easier to interface with than one that requires a special driver.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: USB I/O

Postby Dinosaur » Sat Aug 29, 2009 2:22 pm

Hi Brett

Have now started the process of interfacing to a USB I/O board.
Since your last reply I have finalised the Joystick "Mouse" via the
U-HID board and am very happy with the performance.

I have some reading to do regarding the api, but was hoping you could give me a broad overall picture
as to what is needed in terms of software to Read / Write 50 I/O Pins.
I am proficient in MASM, but will probably be using in-line asm with FreeBasic.
Considering that my software will only ever be used on my machines, and does not have to be a broad
Dos based interface should make the process simpler.

I have also communicated with Andy @ Ultimarc to see if he has any input before I start
what will more then likely be a lengthy process.

REgards
Dinosaur
 
Posts: 70
Joined: Wed Jul 01, 2009 5:54 pm
Location: Salt Lake City USA

Re: USB I/O

Postby Bret » Sun Aug 30, 2009 8:47 am

As you know, the USB drivers are capable of doing some pretty sophisticated things. They are designed to be run in the background, and are designed to automatically notify you of things you may need to know about, such as device disconnects, resets, etc. It is in many respects similar to a rudimentary real-time operating system. For your particular application, though, you shouldn't need any of that advanced functionality.

You're simply going to be periodically polling the device in the foreground, and will only need to call two or three API functions to do that. The first will be to verify that the device is plugged in an powered up, "Find Unregistered Interface". The second will be to poll for the data, either "Schedule Bulk Transaction" or "Schedule Periodic Interrupt Transaction". Which you choose depends on exactly what you're trying to accomplish, since they both have advantages and disadvantages.

Bulk transactions are "one-time" process that can be issued at any time, but it always takes at least a couple of milliseconds to get a response. The transaction must be processed, scheduled, packets sent across the bus, and an IRQ issued when the transaction is complete. It is impossible to get an "instant" response from ANY kind of USB device -- that's just not how the architecture works.

Periodic Interrupt transactions are issued with a periodicity, which indicates how often (in milliseconds) you want the transaction to automatically repeat. The USB hardware automatically updates the same section of memory every time the periodic interrupt happens. You can set it up to be notified automatically (through an IRQ) that the memory has been updated, or you can just monitor it to see when it's changed (initialize it to all 0's or all 1's, for example). This can also be used to test if the device got unplugged somehow (the memory will stop changing). The disadvantage to a Periodic Interrupt comes when you want to stop the polling process. When the Periodic Interrupt request was issued, the API returned some values in the CPU registers that you need to remember in order to issue the "Close Transaction Handle" request.

A lot of the things that happen in the general-purpose drivers, like USBMOUSE, will be things that you won't need to worry about (except perhaps during the development process). For example, USBMOUSE needs to download all of the USB descriptors from the device to figure out if the device is really even a mouse or not, how many buttons and wheels it has, the format of the data (which byte(s) correspond to which axes and wheels), etc. You're already going to know the size and format of the data, so won't need to worry about any of that. The general-purpose drivers also use the registration process of the API to make sure other drivers don't try to take control of the device, which you also should not need to worry about.

It will definitely take some development time, but I don't think it's going to be nearly as difficult as you are imagining right now. You're going to have a lot of control over the environment, so a lot of the "safeguards" needed in a general-purpose environment aren't necessary.

Bret
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: USB I/O

Postby Dinosaur » Sun Aug 30, 2009 9:03 pm

Hi Brett

I have read, and I think I have a fair understanding of the api.
Writing some test routines, I have come across what is a messy problem.
A Transaction request requires a pointer to the 64 byte structure in DS:DX register pair.
However the pointers in most modern compilers are 32 bit linear addresses.
I understand that all the other device drivers (Mouse, Joystick etc) communicate using this interface,
so changing the address to a linear 32 bit address is impractical.

One of FB's asm guru's has responded here,
http://www.freebasic.net/forum/viewtopi ... 651#124651
but I thought perhaps you may have some suggestions.

Regards
Dinosaur
 
Posts: 70
Joined: Wed Jul 01, 2009 5:54 pm
Location: Salt Lake City USA

Re: USB I/O

Postby Bret » Mon Aug 31, 2009 1:40 am

I think that may be your only solution, unless you can figure out a way to address the same piece of memory with both a segment:offset and a linear address. I don't know if that's even possible to do in FreeBASIC.

The other potential issue you'll have is with the "common" memory address used to actually transfer the data. The USB hardware requires a physical memory address, not a linear address. If memory paging is turned off, they are the same, and it is not a problem. You may end up needing some sort of function to convert a linear address to a physical address, though.

You could also just add some extra bytes to the 64-byte API request data structure and use that as your "common" memory space. Again, though, ultimately all addresses must be converted to a physical address as required by the USB hardware. If the data address you provide to the API (within the 64-byte structure) is in segment:offset format, the drivers use VCPI calls to translate the segment:offset to a physical address. I don't know if VCPI is still enabled when FreeBASIC is running (if FreeBASIC uses DPMI it isn't, because DPMI and VCPI are completely incompatible with each other). I've never seen a DPMI call that allows you to translate a segment:offset to a physical address like there is in VCPI -- if there is one, I would certainly like to know about it.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: USB I/O

Postby Dinosaur » Mon Aug 31, 2009 3:19 pm

Hi Brett

While I am testing and consuming all the info, I have two questions.

1. Transaction Request shows DS:DX is required.
Is that the one and only time I need to advise the host of the Struct Address ?

2. When I use say
.I14RRequestType = 1
.I14RHostIndex = 255
and call the Int, where is the Host software Information placed ?
Is it in the Struct, or is it placed in another buffer.
If so where do I nominate the buffer for Data ?

I have read most of the doc's, but if I have missed it (or went in one ear and out the other)
then please point that out.

EDIT: Found the answer to Question 2.
But perhaps you can give me an idea as to which fields of the Struc are essential to be filled in for a simple call like the one above.
I hadn't filled in the DataAddress or DataSize, but sofar this hasnt cured my GPF's


Regards
Dinosaur
 
Posts: 70
Joined: Wed Jul 01, 2009 5:54 pm
Location: Salt Lake City USA

Re: USB I/O

Postby Bret » Tue Sep 01, 2009 3:24 am

Dinosaur wrote:1. Transaction Request shows DS:DX is required.
Is that the one and only time I need to advise the host of the Struct Address ?


You need to advise the host of the structure address (DS:DX) each time you issue an INT 14h request. The host driver does not assume you will be using the same structure each time and "remember" it from the last time. Also, the host driver can receive requests from many different places, and has no idea where the current request is actually coming from. However, once the host driver has finished processing the INT 14h request and returned to the caller, the same structure can immediately be modified and reused by the caller for another purpose. The host driver copies the relevant information it needs to remember from the structure to its internal storage areas and does not need to refer to the data in the structure ever again.

Dinosaur wrote:2. When I use say
.I14RRequestType = 1
.I14RHostIndex = 255
and call the Int, where is the Host software Information placed ?
Is it in the Struct, or is it placed in another buffer.
If so where do I nominate the buffer for Data ?

EDIT: Found the answer to Question 2.
But perhaps you can give me an idea as to which fields of the Struc are essential to be filled in for a simple call like the one above.
I hadn't filled in the DataAddress or DataSize, but sofar this hasnt cured my GPF's


Although you figured out the answer to #2, I'll go ahead and post it here anyway in case anybody else reads this.

First of all, let me say that you are starting the correct way. I14RRequestType = 1 = Get Host SWInfo is a very simple request that just returns some information stored in the host driver itself, and does not require any actual USB packets to traverse the bus. That is a great way to test the basic interface between your protected-mode program and the real-mode INT 14h interface.

For this particular function (GetHostSWInfo), you call INT 14h with:

AX = 5001h
BX = 5553h
CX = 4221h
DS:DX = Address of the 64-byte request structure (must be in the first MB of memory, accessible to real-mode programs)

The 64-byte structure only needs two fields to be filled in:

.I14RRequestType = 1 (GetHostSWInfo)
.I14RHostIndex = 255 (All Hosts)

The rest of the fields in the 64-byte request structure are ignored by the host driver for this particular request (GetHostSWInfo), so it doesn't matter what's in them.

The INT 14h request will return with:

Carry Flag = Clear (No error)
AX = 0 (No error)
BX = 0005h (current API version = 0.05)
CX = FFFFh (No data to return)
DX = FFFFh (No data to return)

All information for this particular request is returned in the CPU registers. Many of the INT 14h requests are like this -- all of the relevant data is returned in the CPU registers (AX, BX, CX, DX, and possibly ES in future versions of the API). Some types of requests require additional fields of the 64-byte request structure to be filled in (like .I14RDataAddress and .I14RDataSize), but this particular one (GetHostSWinfo) does not.

If you're gettng GPF's, it must be because 64-byte data structure is not in memory that is accessible to real-mode programs for some reason, or else you're not issuing the INT 14h request from real mode.

Bret
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: USB I/O

Postby Dinosaur » Fri Sep 04, 2009 11:05 am

Hi Brett

Have resolved the gpf problems, with the help of a FB Forum member.

Can you explain what happens to when the PC is powered up in the following manner.
PC Power
FreeDos boots
USBUHCIL installed but usb devices are already attached to ports.
Mouse driver installed, so now driver has ownership of interface
Other drivers installed (not usb)
Application using usb started but usb ownership is not requested immediatly.
-------------------------------------
Does usbuhcil do anything about devices attached that no "ownership has been claimed for".
Are these devices all "Device 0" ? or are they ignored until I register ownership of Device 0 ?

Regards
Dinosaur
 
Posts: 70
Joined: Wed Jul 01, 2009 5:54 pm
Location: Salt Lake City USA

Re: USB I/O

Postby Bret » Sun Sep 06, 2009 1:35 am

Dinosaur wrote:Have resolved the gpf problems, with the help of a FB Forum member.


Good News!

Dinosaur wrote:Can you explain what happens to when the PC is powered up in the following manner.
PC Power
FreeDos boots
USBUHCIL installed but usb devices are already attached to ports.
Mouse driver installed, so now driver has ownership of interface
Other drivers installed (not usb)
Application using usb started but usb ownership is not requested immediatly.
-------------------------------------
Does usbuhcil do anything about devices attached that no "ownership has been claimed for".
Are these devices all "Device 0" ? or are they ignored until I register ownership of Device 0 ?


When the hub hardware (either the root hub built into the host controller or a remove hub that needs a driver like USBHUB) detects a new device, the hub driver software informs USBUHCIL. USBUHCIL then goes through the lengthy and complicated initialization process for the device. In the middle of the initialization process, the device will temporarily assume address 0, but USBUHCIL will assign it a real address (something between 2 and 17) before the initialization process is complete. During the initialization process, USBUHCIL also downloads the general descriptors for the device, to detect the manufacturer and model number (Vendor ID and Product ID), the quantity and types of interfaces (Device/Interface Class/SubClass/Protocol), and other items such as power requirements and maximum packet sizes for the end points. At the end of the initialization process, the device, and all of its interfaces, are configured and ready for a specific device driver to take over and make the interfaces "useful".

Also at the end of the initialization process, USBUHCIL will also look in the Device 0 Registration table, and immediately notify any drivers that have registered themselves in a manner that matches any of the newly detected interfaces. The Device 0 registration process is really designed for speed and efficiency, particularly in TSR's. Anything that can be discovered by the Device 0 registration process can also be discovered by periodically polling USBUHCIL using the appropriate API calls. The only real difference is that when a driver is registered as a Device 0 owner, USBUHCIL proactively notifies the driver IMMEDIATELY when something happens to a particular class or type of device (including device connects and disconnects), instead of waiting for the driver to ask it.

Keep in mind that all notifications occur as part of an IRQ handler, so efficiency (in terms of time) is critical. The notification handler must do what it needs to do quickly and then return to the caller. That's why it's usually best to write notification handlers in ASM or in-line ASM.

In your particular application, you probably don't need to register as a Device 0 owner. You are in a controlled environment, and you don't necessarily need to know immediately when a device is connected or disconnected. You can simply use the "FInd Unregistered Interface" API call to locate the device when you're ready to start using it. If there's a possibility that the device could be unplugged and you want the user to plug it in, a process like this pseudocode would work:

Code: Select all
  Issue "Find Unregistered Interface" API request
  If correct Device/Interface exists, GOTO Done
  Write message telling user to plug in the device, press <Escape> to cancel
Loop:
  If <Escape> key has been pressed, GOTO Erase
  Issue "Find Unregistered Interface" API request
  If correct Device/Interface does not exist, GOTO Loop
Erase:
  Erase message
Done:


In your application, you may not need to register as the Interface owner, either. One of the main purpose of the Interface registration process to keep two drivers from trying to control the same interface, which would be disastrous. Again, because you are in a controlled environment, you probably won't install two drivers trying to to do the same thing. As with Device 0 registration, you can discover the same things that the notification process would tell you by simply issuing the appropriate API calls, which is probably much easier to do in a foreground application.

I hope that is enough of an explanation to help you move forward.

Bret
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: USB I/O

Postby Dinosaur » Wed Sep 09, 2009 3:30 pm

Hi Brett

Many thanks for that detail, it will help me get a start.

If I plug two boards into the usb host, and one of these devices is claimed
by Mouse device driver, why should the second board be shown as Owned ?
Or has the mouse driver claimed both.?

I can set these boards as different functions, so the second board is setup
as only switch inputs.(A to H)
Code: Select all
USBDEVIC 0.05, (C) 2008, Bret E. Johnson.
Program to display information about Devices attached to the USB Host(s).

                               DEVICE ADDRESSES
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
Host Index:  0  Host Type: UHCI  Bus Type: PCI   IRQ#: 10  Root Hub Ports: 2
Vendor: 1106h = VIA Technologies Inc                       Product: 3038h
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
                DEVICES                                   INTERFACES           
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ  ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
                           L                C  I A                O           
ADRS                       o         P      o  n l                w           
ÍÍÍÍ   (hex)               S         o BUS  n  t t                n           
Test VEND PROD     Sub Pro p USB HUB r POWR f  f I                e     Sub Pro
RWak  ID   ID  Cls Cls col d VER ADR t (mA) g  c n  DESCRIPTION   d Cls Cls col
ÍÍÍÍ ÍÍÍÍ ÍÍÍÍ ÍÍÍ ÍÍÍ ÍÍÍ Í ÍÍÍ ÍÍÍ Í ÍÍÍÍ Í  Í Í ÍÍÍÍÍÍÍÍÍÍÍÍÍÍ Í ÍÍÍ ÍÍÍ ÍÍÍ
  1  1106 3038   9   0   0 . 1.0 ... . s  0 1  0 0*Root Hub       Y   9   0   0
     VIA Technologies Inc                   
ÄÄÄÄ ÄÄÄÄ ÄÄÄÄ ÄÄÄ ÄÄÄ ÄÄÄ Ä ÄÄÄ ÄÄÄ Ä ÄÄÄÄ Ä  Ä Ä ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Ä ÄÄÄ ÄÄÄ ÄÄÄ
  2  D209 1502   0   0   0 . 2.0   1 1  500 1  0 0*USBSUPT1.COM!! .   3   0   0
     Ultimarc?                                 1 0*USBSUPT1.COM!! .   3   0   0
                                               2 0*USBSUPT1.COM!! .   3   0   0
                                               3 0*USBSUPT1.COM!! Y   3   1   2
ÄÄÄÄ ÄÄÄÄ ÄÄÄÄ ÄÄÄ ÄÄÄ ÄÄÄ Ä ÄÄÄ ÄÄÄ Ä ÄÄÄÄ Ä  Ä Ä ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Ä ÄÄÄ ÄÄÄ ÄÄÄ
  3  D209 1501   0   0   0 . 2.0   1 2  500 1  0 0*USBSUPT1.COM!! .   3   0   0
     Ultimarc?                                 1 0*USBSUPT1.COM!! .   3   0   0
                                               2 0*USBSUPT1.COM!! .   3   0   0
                                               3 0*USBSUPT1.COM!! Y   3   1   2



Regards
Dinosaur
 
Posts: 70
Joined: Wed Jul 01, 2009 5:54 pm
Location: Salt Lake City USA

Re: USB I/O

Postby Bret » Thu Sep 10, 2009 2:41 am

USBMOUSE will own all of the USB mice it can find, as many as eight of them. You can have as many as eight USB mice, plus a PS2 mouse, in use on the same computer at the same time. This would let you have several different mice plugged in (a left-handed, a right-handed, a track-ball, a joystick-mouse like you're using, etc.) and not need to worry about un-plugging and re-plugging if you want to switch between them. This could also come in handy in a training situation, where the trainer and trainee could each have their own mouse (and keyboard) instead of needing to move devices or people back and forth constantly during the training session.

Each of your two boards has four interfaces: the I/O, a joystick, a keyboard, and a mouse, even if there's nothing physically hooked up to them. USBMOUSE owns both of the mouse interfaces. If your application wanted to take control away from USBMOUSE for one or both of the mice, there is an API process to do that. If you installed USBKEYB, it would own both of the keyboards, and if you installed USBJSTIK it would own both of the joysitcks. None of the programs would own the I/O interface, though, so you are free to use one or both of those in your FreeBASIC application.

EDIT:

I've been doing a little studying on DPMI, and looking through the posts in the FreeBASIC forum regarding this. Based on what I've seen regarding DPMI, I'm not sure you can provide a physical memory address to USBUHCIL, which is required for the PCI hardware to actually transfer any data to or from a USB device. FYI, this is because the PCI hardware uses Bus Mastering to transfer data, which means that the PCI hardware takes direct control of the memory address lines on the bus and does not involve the CPU at all. Bus Mastering is similar in many ways to DMA, and is why they came up with VDS (Virtual DMA Services) -- real DMA doesn't work correctly in certain cases, like under DPMI. I suggest you try to figure out a way to do it though, if you can. It may require "breaking into" the MMU (Memory Management Unit) or some of the special CPU translation and look-up tables. I suspect some sharp programmer in the FreeBASIC Forum might be able to come up with an answer.

If it turns out to be impossible, there may be a way around it. It will require another new TSR program, though, which essentially triple-buffers the memory transfers. The new program will need to set up a buffer in the first MB of memory, where it is accessible to real-mode programs and where the physical memory address can be known. When data needs to be transferred to a linear address where the physical address is unknown, the data will need to be transferred three times. It will first be transferred to the special buffer that is accessible to both PCI Bus Mastering and to real-mode programs using PCI Bus Mastering. Then, it will be transferred to another special buffer (set up by DPMI calls) that is accessible to both real-mode programs and DPMI using the CPU, similar to what you're doing now to access the real-mode USB API. The final step will be to transfer the data to a linear address directly accessible to DPMI programs, also using the CPU. Obviously, this will slow things down some, but may still be fast enough to not be an issue. Again, if you can provide a physical address corresponding to the linear address where you want the data to ultimately appear, none of this will be necessary.

I actually came up with the basic idea awhile ago when I came across problems with UMBPCI, a program which provides UMBs (Upper Memory Blocks) to DOS without putting the CPU into protected mode the way EMM386 and other memory managers do. The way that UMBPCI provides the memory is by enabling special Shadow RAM hardware on the motherboard. Unfortunately, the Shadow RAM memory used to provide UMBs is not physical memory, and is inaccessible to both DMA and Bus Mastering. USBUHCIL normally loads itself automatically into UMBs, but won't do it if UMBPCI is providing the UMBs because PCI Bus Mastering won't work. A double-buffering program installed in low memory would allow USBUHCIL to install itself into UMBs, since the double-buffering program would be in low memory where a physical memory address can be provided.

The double-buffering program is something I've had in the back of my mind for awhile, but have never done anything with it yet. It would obviously take some time to develop, and would need a special new API. Just thought you should know that even if you can't provide a physical memory address, all is not lost, just perhaps delayed, and also to let you know that DPMI isn't the panacea that MS (and others) claim it is.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: USB I/O

Postby Dinosaur » Thu Sep 10, 2009 10:10 am

Hi Bret

OK, I understand the ownership now. I had also forgotton that although I have set the board up as
inputs only, with no analogue's, the board still reports istself the same as the Mouse board.
The board I have plugged in is not yet a I/O interface.

I'm not sure you can provide a physical memory address to USBUHCIL,

I dont know if you read MichaelW reply and code to my queries.

1.Use dpmi to allocate a 1024 byte Dos memory buffer.
64 bytes for the Struc, and the rest for data transfer.
2. Copy the Struc to Dos memory (works)
3. Get dpmi to issue the Dos Int.
4. Copy the Struc back to Protected mode.(works
5. Read the data. (Response from usbuhcil)

This data transfer works, but are you talking about Callback address for ownership registration ?

Regards
Dinosaur
 
Posts: 70
Joined: Wed Jul 01, 2009 5:54 pm
Location: Salt Lake City USA

Re: USB I/O

Postby Bret » Thu Sep 10, 2009 1:13 pm

I have read MichaelW's comments and responses. What he has provided will handle almost everything, including the callback addresses needed for ownership registration and other notification processes, since those are all part of the API provided by USBUHCIL. In your tests that have been done so far, the data has been transferred either from memory already used by USBUHCIL, or accessed from the host controller through the computer I/O space.

What's still missing is the actual data transfer from a USB device attached to the bus. In your specific case, that will be if you ask the device for its descriptors or for the 50 bits of information regarding the status of the I/O pins. The ONLY way that you can obtain that information is through a physical memory address, since the ONLY way that the host controller transfers that information is by using PCI Bus Mastering. There is no other way to do it.

USBUHCIL must give the USB host controller a physical memory address if the request involves data transfer to or from an actual USB device. If you know the physical address, you can provide it directly to USBUHCIL. You can also provide a segment:offset address to USBUHCIL, and USBUHCIL will translate it into a physical address before sending it to the PCI hardware. However, USBUHCIL can only do this if the CPU is in real mode or in VCPI (which is provided by memory managers like EMM386 and JEMM). As far as I know, there is no call, or series of calls, that can translate a segment:offset address into a physical address (or vice versa) under DPMI. There is a DPMI call available on some DPMI hosts that will assign a linear address to a physical address, but you must know the physical address you want to use (and, obviously, it must not already be used by something else). Unfortunately, as far as I know, DPMI doesn't provide a way to figure out what physical addresses are currently unused. I also don't know if CWSDPMI (or whatever DPMI host you're using) provides that particular function or not. Keep in mind that DPMI is designed by Microsoft to support Windows, and the whole point of Windows is to NOT let you access the real hardware -- you're just supposed to use the virtualized hardware that Windows gives you.

If you can't somehow provide a physical address to go along with the segment:offset address, you'll never be able to get the I/O data out of the USB device without a double- or triple-buffering process. FWIW, some references I've seen regarding Windows makes me think it uses a double-buffering process for USB, at least in certain situations.

Bret
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: USB I/O

Postby Dinosaur » Thu Sep 10, 2009 2:09 pm

Hi Brett

Firstly dont take offence at my persistent questioning.
After many years in design / R&D of machines and systems, I have learned
that sometimes we are so familiar with a subject, that we cant see the wood for the trees.
Not suggesting this is the case here, but bear with me.

1.If The device is attached to the bus, and usbuhcil mounts it, does usbuhcil KNOW the linear address. ?
If so, then the problem is only letting my application know somehow, with a function call.
EDIT: Just reading your reply again, means this makes no sense.

2. When I communicate with a Device, my understanding is that it will always be through usbuhcil.
I did not think that I would be communicating with the device directly.

3.Because I am in a closed environment, is there a third party tool that will show the addresses of all the
devices attached to the bus. If the placement of these devices is predictable on every boot, then I can
hard code these addresses.(or in a config file)

4.I have the option of using almost any dpmi , but with FreeDos I can also load their EMM386 equivalent.

Regards
Dinosaur
 
Posts: 70
Joined: Wed Jul 01, 2009 5:54 pm
Location: Salt Lake City USA

Re: USB I/O

Postby Dinosaur » Thu Sep 10, 2009 9:29 pm

Hi Brett

Just an unrelated question.
I have written a fair amount of code to make the process of evaluating usb easier.
In that process I discovered that after a call to get DvcStatus, it recorded an error in
that bit 0 was set (no other bits were set) but yet there was no error code in DX
although there was a Hex65 in CX for last completed stage.
Is the error code related to the last stage, or to the stage that caused the error ?

Regards
Dinosaur
 
Posts: 70
Joined: Wed Jul 01, 2009 5:54 pm
Location: Salt Lake City USA

Re: USB I/O

Postby Bret » Thu Sep 10, 2009 11:38 pm

Dinosaur wrote:Firstly dont take offence at my persistent questioning.


Not a problem. It's good that you're asking the questions now -- this will help a lot of people later on.

Dinosaur wrote:After many years in design / R&D of machines and systems, I have learned that sometimes we are so familiar with a subject, that we cant see the wood for the trees. Not suggesting this is the case here, but bear with me.


I understand completely. Sometimes the hardest things to see are the ones that are right in front of your face.

Dinosaur wrote:1.If The device is attached to the bus, and usbuhcil mounts it, does usbuhcil KNOW the linear address. ? If so, then the problem is only letting my application know somehow, with a function call.
EDIT: Just reading your reply again, means this makes no sense.


No. Neither USBUHCIL nor the PCI hardware know anything about linear addresses. USBUHCIL only understands and manipulates segment:offset addresses, and the PCI hadrware only understands and manipulates physical addresses.

Also, USBUHCIL does not "mount" a Device, at least not in the same sense that, say, a disk drive is mounted. It simply "turns it on" and enables it to the point where a device driver can "mount" it and make it useful.

Dinosaur wrote:2. When I communicate with a Device, my understanding is that it will always be through usbuhcil. I did not think that I would be communicating with the device directly.


You are correct. You must go through USBUHCIL to ultimately communicate with the device.

USBUHCIL communicates with the USB host controller by placing "instructions" on what it wants the host controller to do in memory (using real/V86 mode segment:offset functions), translating the segment:offset addresses to physical addresses, and telling the host controller what those physical addresses are. The host controller reads the memory where USBUHCIL stored the instructions using Bus Mastering, and does what USBUHCIL told it to do. The host controller issues the appropriate packets across the bus to the Device, and when the transaction is complete the host hardware modifies the memory (again using Bus Mastering) to indicate the status of the packet transaction, and issues an IRQ. When USBUHCIL process the IRQ, it reads the updated memory (using segment:offset) and informs the original requesting program (if the program wanted it to) that the transaction is complete.

All communications with the computer from the host controller (PCI) side is done using Bus Mastering. For instance, if you want to transfer some data to a USB device, included in the "instructions" must be the physical memory address where the data is stored, how many bytes of data to send, and which Device to send it to.

The only way the PCI hardware can communicate with a program running on the computer is through memory, and the only way the PCI hardware can access memory is using Bus Mastering, which requires physical addresses, not linear or segment:offset addresses.

Dinosaur wrote:3.Because I am in a closed environment, is there a third party tool that will show the addresses of all the devices attached to the bus. If the placement of these devices is predictable on every boot, then I can hard code these addresses.(or in a config file)


That depends on which kind of addresses you're talking about. There are memory addresses and there are USB Device addresses. If you're always using the same versions of software and always having the same USB devices plugged into the same ports, everything SHOULD always boot up the same way. But a USB device doesn't have a memory address associated with it at all, and neither does the USB host controller. The only thing that actually has a memory address is USBUHCIL.

I was actually thinking of another option besides creating a new program to solve your particular problem. There is some empty/wasted memory space in USBUHCIL that could be used for small data transfers. You only need to transfer 7 bytes (50 bits rounded up to a byte boundary) of data at a time, which could easily be "borrowed" from USBUHCIL (and USBUHCIL knows the physical address of itself). I would need to add some additional API requests to make this happen, since USBUHCIL would need to manage the memory so only one program can use it at a time. It would be much faster to do that than to create a whole new program, since I would want to add a bunch of additional features to a general purpose double-buffering program. I will probably create such a program in the future, though.

Dinosaur wrote:4.I have the option of using almost any dpmi , but with FreeDos I can also load their EMM386 equivalent.


EMM386 and equivalents just install VCPI, but when you install a DPMI host the VCPI is disabled. Changing DPMI hosts may allow you to assign a linear address to a physical address (assuming CWSDMPI doesn't allow that), but changing EMM drivers probably won't buy you anything. In any case, you still need to find an unused physical address, and I'm not sure any DPMI host will help you there.

**************************************

Dinosaur wrote:In that process I discovered that after a call to get DvcStatus, it recorded an error in
that bit 0 was set (no other bits were set) but yet there was no error code in DX
although there was a Hex65 in CX for last completed stage.
Is the error code related to the last stage, or to the stage that caused the error ?


Which bit 0 was set?
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: USB I/O

Postby Dinosaur » Fri Sep 11, 2009 10:45 am

Hi Brett

Where I am getting confused (it's easy) is the purpose of the linear address.
I misunderstood it to be a linear address of where the "device" is hiding.
So, if usbuhcil translates the Seg:offs address that my app provides to issue a physical address to the host controller, (which is only a place to exchange commands & Data)
then my only problem is to locate such a free address in Real Mode memory area.

This is where I thought that making a buffer for the Struct larger (1024 bytes) to allow room for this would solve that problem.
Equally, I can create another buffer specifically for this.
Am I still missing something ?


I was referring to this call, where bit 0 in BH was set.
But no error code in DX
Get Device Status Information

Class: Device
Return Type: Immediate

Entry:
I14RRequestType = 43h (I14RRTGetDvcStatus)
I14RHostIndex = Host Index (0-15)
I14RDeviceAddress = Address of Device to get Info for

Return (Success):
CF = Clear
AX = 0
BL = Current Configuration Value for Device
BH = Status Flags Bitmap
Bit 0 (01h) = Set if Device is "Bad" (a problem occurred
during the Reset/Enumeration Process)
Bit 1 (02h) = Set if Device supports Remote Wakeup Feature
Bit 2 (04h) = Set if Remote Wakeup Feature is Enabled
Bit 3 (08h) = Set if Test Mode is Enabled
Bits 4-6 = Reserved (0)
Bit 7 (80h) = Set if Device is currently in the middle of the
Reset/Enumeration process
CL = Last Completed Stage of Reset/Enumeration Process
CH = FFh
DX = Error Code Associated with Last Completed Stage of
Reset/Enumeration Process
Edit: Will start a new post for software related questions, as this subject ends up to messy for others to read.
Dinosaur
 
Posts: 70
Joined: Wed Jul 01, 2009 5:54 pm
Location: Salt Lake City USA

Re: USB I/O

Postby c.m » Sat Sep 12, 2009 6:33 am

Regarding the linear-to-physical address translation, maybe HDPMI could be used as DPMI host for your application? Apparently it supports some translated VDS services for the required translation. For details, please refer to the HDPMI manual or ask its maintainer Japheth; I'm not exactly a DPMI expert.

This is from HDPMI.TXT:
Code: Select all
6.7 VDS API

   The following VDS functions (Int 4Bh, AH=81h) are supported in
   protected-mode:

   AL  Function               Comment
   -----------------------------------------------------------------------
   03  lock region            routed to v86-mode with translation of ES:E/DI
   04  unlock region          routed to v86-mode with translation of ES:E/DI
   05  scatter/gather lock    handled by HDPMI. ES:E/DI must point to a EDDS.
   06  scatter/gather unlock  handled by HDPMI. Indeed it is mostly a No-Op,
                              just the parameters are checked for validity.
   07  request DMA buffer     routed to v86-mode with translation of ES:E/DI
   08  release DMA buffer     routed to v86-mode with translation of ES:E/DI
   09  copy into DMA buffer   routed to v86-mode with translation of ES:E/DI
   0A  copy out of DMA buffer routed to v86-mode with translation of ES:E/DI

   VDS functions 02 and 0Bh-0Ch are routed to real/v86-mode without
   translation.
   Implementation of function 05 will allow linear-to-physical address
   translation for any valid linear address. If an address space contains
   uncommitted pages, bit 6 of DX must be set to return PTEs, else the call
   will fail.
   Functions which are routed to v86-mode with ES:E/DI translation will not
   be able to handle linear addresses managed by HDPMI, that is, they might
   work for address space 0-110000h only.
   
   Please be aware that if DOS is running in real-mode (no EMM is loaded),
   then calling functions other than 05-06 most likely will fail. Therefore
   bit 5 at 40h:007Bh should be checked if VDS is available.
C. Masloch
c.m
 
Posts: 18
Joined: Sat Sep 12, 2009 5:49 am
Location: Germany

Re: USB I/O

Postby Dinosaur » Sat Sep 12, 2009 1:06 pm

Hi All

I have re-raed the entire thread and drew some snippets from the posts
and collected them below.

unless you can figure out a way to address the same piece of memory with both a segment:offset and a linear address


Yes, I can copy from Protected mode memory to Real Mode memory and back again.

The other potential issue you'll have is with the "common" memory address used to actually transfer the data

The USB hardware requires a physical memory address, not a linear address

Based on what I've seen regarding DPMI, I'm not sure you can provide a physical memory address to USBUHCIL


Perhaps not, BUT

You can also provide a segment:offset address to USBUHCIL, and USBUHCIL will translate it into a physical address before sending it to the PCI hardware


Great

So, in other words, If I provide usbuhcil with seg:offs address of my data buffer, usbuhcil will translate this to
a physical address for the use by the Host Hardware.

However, USBUHCIL can only do this if the CPU is in real mode or in VCPI


So here is the real question. We dont know if any dpmi will actually switch to real mode
for Int 14 or just emulate it.

The only other question I have then, is the area of memory important.
In other words any block in the first mByte will do ?
That means then, that I can load a small program prior to usbuhcil and reserve a block of memory.

CM, thanks for that, but if the capability of usbuhcil to convert is correct, then there is no need to
use any dpmi services for this.

Regards
Dinosaur
 
Posts: 70
Joined: Wed Jul 01, 2009 5:54 pm
Location: Salt Lake City USA

Re: USB I/O

Postby c.m » Sat Sep 12, 2009 8:59 pm

Dinosaur wrote:
However, USBUHCIL can only do this if the CPU is in real mode or in VCPI


So here is the real question. We dont know if any dpmi will actually switch to real mode
for Int 14 or just emulate it.


I think this depends on the CPU mode the DPMI host found when it installed. When no VCPI host/EMM was found and the CPU was in real mode, the DPMI host probably switches to real mode (instead of V86) to handle interrupts.

The only other question I have then, is the area of memory important.
In other words any block in the first mByte will do ?
That means then, that I can load a small program prior to usbuhcil and reserve a block of memory.


There are some standard DPMI calls to allocate DOS memory, too. They're translated to DOS calls, so you can actually allocate the memory from your application.
C. Masloch
c.m
 
Posts: 18
Joined: Sat Sep 12, 2009 5:49 am
Location: Germany

Re: USB I/O

Postby Dinosaur » Sat Sep 12, 2009 9:08 pm

Hi all

C.m, I have actually already allocated dos PM memory, but our discussion above gave me the impression that it wasnt enough.
Actually, there are no obstacles if my summation and your assumption about "switching to Real Mode" is correct.

I will read the dpmi doc's again, and see if I can find that.

From a programming point of view though, I am not getting the expected results according to the doc's.

Regards
Dinosaur
 
Posts: 70
Joined: Wed Jul 01, 2009 5:54 pm
Location: Salt Lake City USA

Re: USB I/O

Postby c.m » Sun Sep 13, 2009 2:18 am

With "DOS PM memory", you probably refer to the DPMI memory which is allocated using Int31.05 subfunctions. I was refering to DOS real mode memory, which can be allocated from a DPMI application using Int31.01 subfunctions. This allocates the same memory directly available to real mode DOS applications in the first MiB, while the DPMI memory is (usually) above 1 MiB.
C. Masloch
c.m
 
Posts: 18
Joined: Sat Sep 12, 2009 5:49 am
Location: Germany

Next

Return to Programs

Who is online

Users browsing this forum: No registered users and 1 guest

cron