private GarminUSBPacket GetPacket() { GarminUSBPacket packet; var bufferSize = 0; var buffer = new byte[0]; while (true) { // Read async data until the driver returns less than the // max async data size, which signifies the end of a packet var tempBuffer = new byte[APIs.ASYNC_DATA_SIZE]; int bytesReturned; IntPtr pInBuffer = Marshal.AllocHGlobal(0); IntPtr pOutBuffer = Marshal.AllocHGlobal(APIs.ASYNC_DATA_SIZE); bool r = APIs.DeviceIoControl( handle.ToInt32(), CTL_CODE(0x00000022, 0x850, 0, 0), pInBuffer, 0, pOutBuffer, APIs.ASYNC_DATA_SIZE, out bytesReturned, 0); Marshal.Copy(pOutBuffer, tempBuffer, 0, APIs.ASYNC_DATA_SIZE); Marshal.FreeHGlobal(pInBuffer); Marshal.FreeHGlobal(pOutBuffer); if (!r) { throw new GarminUsbException(Strings.ErrorCommunicatingWithDevice); } bufferSize += APIs.ASYNC_DATA_SIZE; var newBuffer = new byte[bufferSize]; if (buffer.Length > 0) { Array.Copy(buffer, 0, newBuffer, 0, buffer.Length); } Array.Copy(tempBuffer, 0, newBuffer, bufferSize - APIs.ASYNC_DATA_SIZE, tempBuffer.Length); buffer = newBuffer; if (bytesReturned != APIs.ASYNC_DATA_SIZE) { packet = new GarminUSBPacket(buffer); break; } } // If this was a small "signal" packet, read a real // packet using ReadFile if (packet.Type == 0 && packet.Id == 2) { var newBuffer = new byte[MAX_BUFFER_SIZE]; var bytesReturned = 0; // A full implementation would keep reading (and queueing) // packets until the driver returns a 0 size buffer. bool r = APIs.ReadFile(handle, newBuffer, MAX_BUFFER_SIZE, ref bytesReturned, IntPtr.Zero); if (!r) { throw new GarminUsbException(Strings.ErrorCommunicatingWithDevice); } return(new GarminUSBPacket(newBuffer)); } return(packet); }
private void StartUSBCommunication() { ReadingNow = true; var guid = new Guid("2C9C45C2-8E7D-4C08-A12D-816BBAE722C0"); string deviceId; const int portIndex = 0; IntPtr hDevInfoSet = APIs.SetupDiGetClassDevs(ref guid, 0, IntPtr.Zero, (int)(APIs.DeviceFlags.DigCDDeviceInterface | APIs.DeviceFlags.DigCFPresent)); APIs.DeviceInterfaceDetailData mDetailedData = GetDeviceInfo(hDevInfoSet, guid, out deviceId, portIndex); handle = APIs.CreateFile(mDetailedData.DevicePath, FileAccess.Read | FileAccess.Write, FileShare.None, IntPtr.Zero, FileMode.Open, 0x00000080, IntPtr.Zero); // Did we get a handle? if ((int)handle < 0) { throw new GarminUsbException(Strings.ErrorFindingDevice); } IntPtr usbPacketSizePointer = Marshal.AllocHGlobal(sizeof(Int16)); int bytesReturned; bool r = APIs.DeviceIoControl( handle.ToInt32(), CTL_CODE(0x00000022, 0x851, 0, 0), IntPtr.Zero, 0, usbPacketSizePointer, (uint)sizeof(int), out bytesReturned, 0); if (!r) { throw new GarminUsbException(Strings.ErrorCommunicatingWithDevice); } usbPacketSize = (Int16)Marshal.PtrToStructure(usbPacketSizePointer, typeof(Int16)); Marshal.FreeHGlobal(usbPacketSizePointer); // Tell the device that we are starting a session. var startSessionPacket = new GarminUSBPacket { Id = 5 }; SendPacket(startSessionPacket); GarminUSBPacket packet; while (true) { packet = GetPacket(); if (packet.Type == 0 && packet.Id == 6) { break; } } }