BULK TRANSACTION HELP

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.

BULK TRANSACTION HELP

Postby qfab » Thu Nov 19, 2009 1:20 pm

Hello Bret,

Beyond your documentation in the .zips, can you send an example of Bulk transactions using C (I'm using a very old version of MSVC V1.52 compiled for DOS)? I'm booting MSDOS-622 (totally non-windows env) and using your USBUHCIL driver to communicate with an I2C programming module. Using "USBUHCIL Descriptors 2", I can see the module, end points for in/out, etc.

I can read the DeviceId, VendorId, etc., but I cannot seem to make a bulk transfer work. The LED on the device blinks when I send data but I'm obviously missing something here.

The device vendor has given me a command set to read the device software version back but I always read null. I've tried many variations of this but still null.

Thanks,
-jeff


Example of my code:

in main.........
GetDeviceInfo(0,2); //works, get device info, VendorID, DeviceID, on hub port

//host to device
strcpy(deviceData,"SendBuffer[0]:=1;");
dataSize=strlen(deviceData);
UsbTalk(0,0,2,dataSize,deviceData,cbakAddrPtr);

//host to device
strcpy(deviceData,"SendBuffer[1]:=$F0;");
dataSize=strlen(deviceData);
UsbTalk(0,0,2,dataSize,deviceData,cbakAddrPtr);

//device to host
strcpy(deviceData,'\0');
UsbTalk(1,0,2,1,deviceData,cbakAddrPtr);
printf("USBTALK : %s - %s\n",deviceData,cbakAddrPtr);

.....

//send transaction Host to Device
int UsbTalk(int Direction, int HostIndex, int DeviceIndex, int numBytes, char *deviceData, char *cbakAddrPtr)
{
int ReturnValue; //Return value from Subroutine Calls
int AXRegister; //Return AX Register
int BXRegister; //Return BX Register
int CXRegister; //Return CX Register
int DXRegister; //Return DX Register

//clear data at dataAddrPtr
//strcpy(dataAddrPtr,deviceData);

//set Schedule structure
Int14RequestPtr->I14RRequestType = I14RRTDoBulk; //Request Type = 0x97 Schedule Bulk Transaction
Int14RequestPtr->I14RHostIndex = HostIndex; //Host Index
Int14RequestPtr->I14RDeviceAddress = DeviceIndex; //DeviceIndex
Int14RequestPtr->I14REndPoint = 2; //Device endpoint
Int14RequestPtr->I14RTimeout = 50; //5 second timeout
//Int14RequestPtr->I14RDataAddrSeg = _FP_SEG(deviceData); //address of send data
Int14RequestPtr->I14RDataAddrOff = _FP_OFF(deviceData); //address of send data
//Int14RequestPtr->I14RCallBackAddrSeg = _FP_SEG(cbakAddrPtr); //address of call back data
//Int14RequestPtr->I14RCallBackAddrOff = _FP_OFF(cbakAddrPtr); //address of call back data
Int14RequestPtr->I14RUserPktID = 0x0; //value to return in BX on notification

//set USB data direction and size
if(Direction==1)
{
//device to host
Int14RequestPtr->I14RFlags = I14RFlagIn; //data direction Device to Host
Int14RequestPtr->I14RDataSize = numBytes; //bytes to Transfer (0-65535)
strcpy(deviceData,'\0');
} else
{
//host to device
Int14RequestPtr->I14RFlags = I14RFlagOut; //data direction Host to Device
Int14RequestPtr->I14RDataSize = strlen(deviceData); //bytes to Transfer (0-65535)
//strcpy(dataAddrPtr,deviceData);
}

//send the request interrupt
ReturnValue = Int14SendRequest(&AXRegister, &BXRegister, &CXRegister, &DXRegister);

//if error
if(ReturnValue != 0)
{
printf("\nDataOut Error: %d\n",ReturnValue);
printf("AX:%x\n",(AXRegister));
printf("BX:%x\n",(BXRegister));
printf("CX:%x\n",(CXRegister));
printf("DX:%x\n",(DXRegister));
return 1;
}

//if device to host
//if(Direction==1) strcpy(deviceData,dataAddrPtr);

//clear dataAddrPtr
//strcpy(dataAddrPtr,'\0');

//show debug info
printf("Direction : %d\n",Direction);
printf("HostIndex : %d\n",HostIndex);
printf("DeviceIndex: %d\n",DeviceIndex);
printf("NumBytes : %d\n",numBytes);
//printf("DataAddrPtr: %x\n",&dataAddrPtr); //shows pointer address
printf("Device Data: %s\n",deviceData); //shows data at pointer address
printf("DDAddress : %x\n",&deviceData);
return 0;
}

/==========================================================================
// Send a "standard" Int 14h Request to a USB Driver
//==========================================================================
int Int14SendRequest
(
int *AXRegister, //CPU AX Register
int *BXRegister, //CPU BX Register
int *CXRegister, //CPU CX Register
int *DXRegister //CPU DX Register
)
{
static union REGS Regs;
Regs.x.ax = I14AXDoFunction; //AX = 5001 (Do Function)
Regs.x.bx = I14BXInput; //BX = US
Regs.x.cx = I14CXInput; //CX = B!
Regs.x.dx = FP_OFF(Int14RequestPtr); //DS:[DX] = Request Structure

int86(0x14,&Regs,&Regs); //Do Int 14h (USB Request)
*AXRegister = Regs.x.ax; //Set return AX
*BXRegister = Regs.x.bx; //Set return BX
*CXRegister = Regs.x.cx; //Set return CX
*DXRegister = Regs.x.dx; //Set return DX

//debug display
if(Regs.x.ax)
{
printf("\nInt14SendRequest\n");
printf("AX:%x\n",Regs.x.ax);
printf("BX:%x\n",Regs.x.bx);
printf("CX:%x\n",Regs.x.cx);
printf("DX:%x\n",Regs.x.dx);
}
return (Regs.x.ax); //Set return function value
}

//--------------------------------------------------------------------------
//Issue Get Host Hardware Info Request
//--------------------------------------------------------------------------
int GetDeviceInfo(int HostIndex, int DeviceIndex) //USB Host Index, Device Index on USB Host Index
{
int ReturnValue; //Return value from Subroutine Calls
int AXRegister; //Return AX Register
int BXRegister; //Return BX Register
int CXRegister; //Return CX Register
int DXRegister; //Return DX Register
Int14RequestPtr->I14RRequestType = I14RRTGetDvcClassInfo; //Request Type
Int14RequestPtr->I14RHostIndex = HostIndex; //Host Index
Int14RequestPtr->I14RDeviceAddress = DeviceIndex; //DeviceIndex
ReturnValue = Int14SendRequest(&AXRegister, &BXRegister, &CXRegister, &DXRegister);
//if error
if(ReturnValue != 0)
{
printf("\nWriteHostClass Error\n");
printf("AX:%x\n",(AXRegister));
printf("BX:%x\n",(BXRegister));
printf("CX:%x\n",(CXRegister));
printf("DX:%x\n",(DXRegister));
return 0;
}
//no error, print USB type
//printf("\nGetDeviceInfo(Host:%d Device:%d)\n",HostIndex,DeviceIndex);


printf("\nHost:%d Device:%d Class:%x SubClass:%x Proto:%x USB:V%x.%x",HostIndex,DeviceIndex,
(BXRegister & 0xF),(BXRegister & 0xF0),(CXRegister & 0xF),(CXRegister>>8 & 0xF),(CXRegister>>12 & 0xF));

//get VendorID and DeviceID
Int14RequestPtr->I14RRequestType = I14RRTGetDvcVendInfo; //Request Type
Int14SendRequest(&AXRegister, &BXRegister, &CXRegister, &DXRegister);
if(ReturnValue != 0)
{
printf("\nDevice ID Error\n");
printf("AX:%x\n",(AXRegister));
printf("BX:%x\n",(BXRegister));
printf("CX:%x\n",(CXRegister));
printf("DX:%x\n",(DXRegister));
return 0;
} else
{
printf(" VenID:%x DevID:%x\n",BXRegister,CXRegister);
}
//get Device Status
Int14RequestPtr->I14RRequestType = I14RRTGetDvcStatus; //Request Type
Int14SendRequest(&AXRegister, &BXRegister, &CXRegister, &DXRegister);
if(ReturnValue != 0)
{
printf("\nGetDeviceStatus Error\n");
printf("AX:%x\n",(AXRegister));
printf("BX:%x\n",(BXRegister));
printf("CX:%x\n",(CXRegister));
printf("DX:%x\n",(DXRegister));
return 0;
} else
{
printf(" Config:%x Bad:%x Resetting:%x Error:%x\n",
(BXRegister & 0xff), //Write device current configuration data
(BXRegister >> 8 & 0x1), //set if device is bad during enumeration
(BXRegister >> 14 & 0x1), //set if device is still resetting
(DXRegister)); //error number if device enumeration error
}
return ReturnValue;
}
qfab
 
Posts: 4
Joined: Thu Nov 19, 2009 9:46 am

Re: BULK TRANSACTION HELP

Postby Bret » Mon Nov 23, 2009 12:10 am

I don't have an example in C, but it looks like you're almost there. I see a couple of areas where you might be going wrong, though.

[quote="qfab"]//host to device
strcpy(deviceData,"SendBuffer[0]:=1;");

I have a hard time believing that the device will actually respond if you send it the string "SendBuffer[0]:=1;". You probably just want to do this:

SendBuffer[0] = 1;
UsbTalk (0, 0, 2, 1, deviceData, cbakAddrPtr);

Also, what does the code at cbakAddrPtr look like? In general, C compilers do not provide a generic way to do external call-backs. You may just want to set the cbakAddrPtr to a null value (0:FFFFh), and wait for the data to appear in the buffer.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: BULK TRANSACTION HELP

Postby wimpie » Mon Nov 23, 2009 7:05 am

Hallo Jeff,

Since you are using an old compiler, I pulled my old IBM C/2 Version 1.1 compiler from 1988 out of the dust. Before attempting to use it, I produced a working program written in assembler and compiled it with Borland Turbo assembler for OS/2 Version 4.1. Thanks to the excellent written api documentation I succeeded to access my homemade usb device and got it to operate under IBM PC DOS 7.0 exactly the same as it does under OS/2 Warp 4.0.

However switching to the IBM C/2 Compiler was harder. It appears that the int86x routine could not reliably be used for the int 0x14 processing. The carry flag and the result returned and in the ax register were always wrong. Therefore I produced my own assembly language interface using turbo assembly. I am more of an assembler programmer than a C programmer.

.386p
model use16 large,c
ideal

codeseg
public xs2usb
proc xs2usb
arg @@pass:word
uses di,ds,si
mov di,[@@pass]
mov ax,[di+0]
mov bx,[di+2]
mov cx,[di+4]
mov dx,[di+6]
mov di,[di+8]
mov si,ds
mov ds,di
stc ; preset
int 14h ; usbdos
cld ; ensure
mov ds,si
mov di,[@@pass]
mov [di+0],ax
mov [di+2],bx
mov [di+4],cx
mov [di+6],dx
ret ; return
endp xs2usb
end

And to use that interface for bulk transfer in the IBM C/2 program:

// external prototypes
void far xs2usb(short*);

// internal prototypes
void AwaitComplete(void);
void far CallBack(void);
void fail(void);

// define xs2usb parameters
short pass[5]; // ax,bx,cx,dx,ds

// bulk - block transfer - supply data
ReqPacket->I14RRequestType = I14RRTDoBulk;
ReqPacket->I14RCallBackAddr = CallBack;
ReqPacket->I14RDataAddress = BulkSupply;
ReqPacket->I14RDataSize = 0x0014;
ReqPacket->I14REndPoint = 1;
ReqPacket->I14RFlags = 0;
pass[0] = 0x5001; // request
pass[1] = 0x5553; // "US"
pass[2] = 0x4221; // "B!"
pass[3] = FP_OFF(ReqPacket);
pass[4] = FP_SEG(ReqPacket);
Requests++; // outstanding
xs2usb(pass); //usbdos
if (pass[0]) fail();

void AwaitComplete(void) {
// check request complete
while (Requests) {
// wait 1 millisecond
inregs.h.ah = 0x86; // wait
inregs.x.cx = 0x0000; //high
inregs.x.dx = 0x0400; //low
int86(0x15,&inregs,&outregs);
};
return;
}

void far CallBack(void) {
// update requests counter
Requests--; // outstanding
return;
}

void fail(void) {
// exit with failure message
bdos(9,offset(MsgFailure),0);
exit(4); // failure
}

Greetinigs,
Wim.
wimpie
 
Posts: 11
Joined: Fri Nov 20, 2009 11:52 pm

Re: BULK TRANSACTION HELP

Postby qfab » Wed Dec 02, 2009 1:18 pm

Bret,

USBUHCI or USBUHCIL needs a modification (maybe it's already there and I just don't see it). I'm using MS-DOS on motherboards with BIOS USB and Legacy USB features enabled. When loading the USBUHCI(L) TSR's, they always prompt with an "Are You Sure ..." warning but there is no way to automatically say Yes. I think there needs to be a command line argument that supresses this message or at least allows you to specify /Yes or /No from the command prompt. In my situation for production test equipment, I would never want to have to rely on a low skilled test operator to respond to a prompt like this.

Can you please make this change in your next release?

Thanks,
-jeff
qfab
 
Posts: 4
Joined: Thu Nov 19, 2009 9:46 am

Re: BULK TRANSACTION HELP

Postby Bret » Wed Dec 02, 2009 2:31 pm

There are two existing options for this, /DisableLegacy and /DisableOther. /DisableLegacy is used when the BIOS is controlling the hardware, and the BIOS is configured the way the it is supposed to be according to Microsoft's unofficial documentation. /DisableOther is used when some other non-BIOS program is controlling the hardware, or the BIOS is doing it "incorrectly" so that it looks like a non-BIOS program is controlling it.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM

Re: BULK TRANSACTION HELP

Postby qfab » Thu Dec 03, 2009 5:52 am

Bret,

I see that I can use USBUHCIL /DisableLegacy /DisableOther and that suppresses the message but also disables those options.

What if I want to not disable but still suppress the message? I'm trying to use a USB barcode scanner that I want to be handled by the BIOS or USB Legacy keyboard support and I'm using a USB I2C programming device via my software and the USBUHCI driver.

Is that possible?

Thanks,
-jeff
qfab
 
Posts: 4
Joined: Thu Nov 19, 2009 9:46 am

Re: BULK TRANSACTION HELP

Postby Bret » Thu Dec 03, 2009 1:31 pm

That's not possible if the devices are on the same Host Controller (same PCI search Index). Only one driver can be controlling the host at one time: it will either be the BIOS, USBUHCI{L}, or some other program. The only way to use separate software protocols is to have separate host controllers.
Bret
 
Posts: 478
Joined: Fri Oct 10, 2008 3:43 am
Location: Rio Rancho, NM


Return to Programs

Who is online

Users browsing this forum: No registered users and 3 guests

cron