?? usbsdk.c
字號:
// This file contains sample code to help application developers
// interface with Garmin USB units. This should not be viewed as a
// full implementation of PC to unit communication. It does not include
// error checking and other elements of a full implementation.
// Also, there are notes in the code suggesting other elements that
// might be necessary.
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <initguid.h>
#include <setupapi.h> // You may need to explicitly link with setupapi.lib
#include <winioctl.h>
DEFINE_GUID(GUID_DEVINTERFACE_GRMNUSB, 0x2c9c45c2L, 0x8e7d, 0x4c08, 0xa1, 0x2d, 0x81, 0x6b, 0xba, 0xe7, 0x22, 0xc0);
#define IOCTL_ASYNC_IN CTL_CODE (FILE_DEVICE_UNKNOWN, 0x850, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_USB_PACKET_SIZE CTL_CODE (FILE_DEVICE_UNKNOWN, 0x851, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define MAX_BUFFER_SIZE 4096
#define ASYNC_DATA_SIZE 64
//-----------------------------------------------------------------------------
HANDLE gHandle;
DWORD gUSBPacketSize;
//-----------------------------------------------------------------------------
#pragma pack( push, 1)
typedef struct
{
unsigned char mPacketType;
unsigned char mReserved1;
unsigned short mReserved2;
unsigned short mPacketId;
unsigned short mReserved3;
unsigned long mDataSize;
BYTE mData[1];
} Packet_t;
#pragma pack( pop)
//-----------------------------------------------------------------------------
void
SendPacket
(
Packet_t aPacket
)
{
DWORD theBytesToWrite = sizeof( aPacket ) - 1 + aPacket.mDataSize;
DWORD theBytesReturned = 0;
WriteFile( gHandle,
&aPacket,
theBytesToWrite,
&theBytesReturned,
NULL );
// If the packet size was an exact multiple of the USB packet
// size, we must make a final write call with no data
if( theBytesToWrite % gUSBPacketSize == 0 )
{
WriteFile( gHandle,
0,
0,
&theBytesReturned,
NULL );
}
}
//-----------------------------------------------------------------------------
// Gets a single packet. Since packets may come simultaneously through
// asynchrous reads and normal (ReadFile) reads, a full implementation
// may require a packet queue and multiple threads.
Packet_t*
GetPacket
(
)
{
Packet_t* thePacket = 0;
DWORD theBufferSize = 0;
BYTE* theBuffer = 0;
for( ; ; )
{
// Read async data until the driver returns less than the
// max async data size, which signifies the end of a packet
BYTE theTempBuffer[ASYNC_DATA_SIZE];
BYTE* theNewBuffer = 0;
DWORD theBytesReturned = 0;
DeviceIoControl( gHandle,
IOCTL_ASYNC_IN,
0,
0,
theTempBuffer,
sizeof( theTempBuffer ),
&theBytesReturned,
NULL );
theBufferSize += ASYNC_DATA_SIZE;
theNewBuffer = (BYTE*) malloc( theBufferSize );
memcpy( theNewBuffer, theBuffer, theBufferSize - ASYNC_DATA_SIZE );
memcpy( theNewBuffer + theBufferSize - ASYNC_DATA_SIZE,
theTempBuffer,
ASYNC_DATA_SIZE );
free( theBuffer );
theBuffer = theNewBuffer;
if( theBytesReturned != ASYNC_DATA_SIZE )
{
thePacket = (Packet_t*) theBuffer;
break;
}
}
// If this was a small "signal" packet, read a real
// packet using ReadFile
if( thePacket->mPacketType == 0 &&
thePacket->mPacketId == 2 )
{
BYTE* theNewBuffer = (BYTE*) malloc( MAX_BUFFER_SIZE );
DWORD theBytesReturned = 0;
free( thePacket );
// A full implementation would keep reading (and queueing)
// packets until the driver returns a 0 size buffer.
ReadFile( gHandle,
theNewBuffer,
MAX_BUFFER_SIZE,
&theBytesReturned,
NULL );
return (Packet_t*) theNewBuffer;
}
else
{
return thePacket;
}
}
//-----------------------------------------------------------------------------
void
Initialize
(
)
{
// Make all the necessary Windows calls to get a handle
// to our USB device
DWORD theBytesReturned = 0;
PSP_INTERFACE_DEVICE_DETAIL_DATA theDevDetailData = 0;
SP_DEVINFO_DATA theDevInfoData = { sizeof( SP_DEVINFO_DATA ) };
Packet_t theStartSessionPacket = { 0, 0, 0, 5, 0 , 0 };
Packet_t* thePacket = 0;
HDEVINFO theDevInfo = SetupDiGetClassDevs(
(GUID*) &GUID_DEVINTERFACE_GRMNUSB,
NULL,
NULL,
DIGCF_PRESENT | DIGCF_INTERFACEDEVICE );
SP_DEVICE_INTERFACE_DATA theInterfaceData;
theInterfaceData.cbSize = sizeof( theInterfaceData );
if( !SetupDiEnumDeviceInterfaces( theDevInfo,
NULL,
(GUID*) &GUID_DEVINTERFACE_GRMNUSB,
0,
&theInterfaceData ) &&
GetLastError() == ERROR_NO_MORE_ITEMS )
{
gHandle = 0;
return;
}
SetupDiGetDeviceInterfaceDetail(
theDevInfo,
&theInterfaceData,
NULL,
0,
&theBytesReturned,
NULL );
theDevDetailData =
(PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc( theBytesReturned );
theDevDetailData->cbSize = sizeof( SP_INTERFACE_DEVICE_DETAIL_DATA );
SetupDiGetDeviceInterfaceDetail( theDevInfo,
&theInterfaceData,
theDevDetailData,
theBytesReturned,
NULL,
&theDevInfoData );
gHandle = CreateFile(
theDevDetailData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
free( theDevDetailData );
// Get the USB packet size, which we need for sending packets
DeviceIoControl( gHandle,
IOCTL_USB_PACKET_SIZE,
0,
0,
&gUSBPacketSize,
sizeof( gUSBPacketSize ),
&theBytesReturned,
NULL );
// Tell the device that we are starting a session.
SendPacket( theStartSessionPacket );
// Wait until the device is ready to the start the session
for( ; ; )
{
thePacket = GetPacket();
if( thePacket->mPacketType == 0 &&
thePacket->mPacketId == 6 )
{
break;
}
free( thePacket );
}
free( thePacket );
}
//-----------------------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
Packet_t theProductDataPacket = { 20, 0, 0, 254, 0 , 0 };
Packet_t* thePacket = 0;
Initialize();
if( gHandle == 0 )
{
printf( "%s", "No device" );
return 0;
}
// Tell the device to send product data
SendPacket( theProductDataPacket );
// Get the product data packet
for( ; ; )
{
thePacket = GetPacket();
if( thePacket->mPacketType == 20 &&
thePacket->mPacketId == 255 )
{
break;
}
free( thePacket );
}
// Print out the product description
printf( "%s", (char*) &thePacket->mData[4] );
free( thePacket );
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -