Serial number of the usb on windows Ce 6.0 in c# - c#

I need to get the serial number of a usb stick connected to a windows ce 6.0 device. I tried with KernelIoControl and i get the serial number of the window ce 6.0 device but not the usb connected to it.
private static string GetDeviceID()
{
// Initialize the output buffer to the size of a
// Win32 DEVICE_ID structure.
byte[] outbuff = new byte[20];
Int32 dwOutBytes;
bool done = false;
Int32 nBuffSize = outbuff.Length;
// Set DEVICEID.dwSize to size of buffer. Some platforms look at
// this field rather than the nOutBufSize param of KernelIoControl
// when determining if the buffer is large enough.
BitConverter.GetBytes(nBuffSize).CopyTo(outbuff, 0);
dwOutBytes = 0;
// Loop until the device ID is retrieved or an error occurs.
while (!done)
{
if (KernelIoControl(IOCTL_HAL_GET_DEVICEID, IntPtr.Zero,
0, outbuff, nBuffSize, ref dwOutBytes))
{
done = true;
}
else
{
int error = Marshal.GetLastWin32Error();
switch (error)
{
case ERROR_NOT_SUPPORTED:
throw new NotSupportedException(
"IOCTL_HAL_GET_DEVICEID is not supported on this device",
new Win32Exception(error));
case ERROR_INSUFFICIENT_BUFFER:
// The buffer is not big enough for the data. The
// required size is in the first 4 bytes of the output
// buffer (DEVICE_ID.dwSize).
nBuffSize = BitConverter.ToInt32(outbuff, 0);
outbuff = new byte[nBuffSize];
// Set DEVICEID.dwSize to size of buffer. Some
// platforms look at this field rather than the
// nOutBufSize param of KernelIoControl when
// determining if the buffer is large enough.
BitConverter.GetBytes(nBuffSize).CopyTo(outbuff, 0);
break;
default:
throw new Win32Exception(error, "Unexpected error");
}
}
}
When i connect the usb stick to the windows ce 6 device, it shows me a new hard disk recognize, i need to come to the properties of this new device registered, get control of the usb ports available on my windows ce 6 device.

What you're probably looking for is USB_DEVICE_DESCRIPTOR. In big windows, you would use SetupDiGetDeviceProperty to get this information, but in CE this value is only available to the driver. I don't think there is a generic way of getting this information back from the driver in CE. Your driver may contain a special IOCTL_ to get that information, though. Contact your OEM.

Related

How to write data to USB HID device in Android with only a single input endpoint

I have a USB HID device that I would like to communicate with. I am successfully doing so on Windows using the HidSharp library (link: https://github.com/treehopper-electronics/HIDSharp). My Windows application is developed using the .NET Framework 4.5, C#, and Visual Studio.
I now want to communicate with this same USB HID device from an Android tablet instead of from the Windows desktop. I am encountering some problems doing so. When I have the device plugged in to my tablet, it reports a single interface with a single "read" endpoint. Here is what is reported to me:
Interface #0
Class: Human Interaction Device (0x3)
Endpoint: #0
Address : 0x81 (10000001)
Number : 1
Direction : Inbound (0x80)
Type : Intrrupt (0x3)
Poll Interval : 1
Max Packet Size: 64
Attributes : 000000011
As you can see, it only reports a single endpoint, which is an inbound endpoint. I need to be able to output simple commands to this device, which I was able to do so successfully on Windows using HidSharp.
HidSharp abstracted everything into a single "stream" object that you could read from and write to. Using the Android APIs, there isn't a single "stream" object, but rather there seem to be 3 different ways of reading/writing: bulk transfer, control transfer, and USB Request. I've tried sending out data using all 3, but with seemingly no success.
Any suggestions on what to do? Is there a reason why I could send out data to this device on Windows, but seemingly cannot do so from Android? Is there a way to use a single endpoint as both a read and a write endpoint? Is there something that I am just obviously missing and not understanding?
I am using Xamarin as my development environment (C#, Visual Studio 2017). Since code is always helpful, here is how I am connecting to the device:
int VendorID = 0x04d8;
int ProductID = 0x2742;
UsbManager USB_Manager = null;
UsbDevice USB_Device = null;
UsbDeviceConnection DeviceConnection = null;
UsbInterface DeviceInterface = null;
UsbEndpoint OutputEndpoint = null;
UsbEndpoint InputEndpoint = null;
//Grab the Android USB manager and get a list of connected devices
var USB_Manager = MyMainActivity.ApplicationContext.GetSystemService(Android.Content.Context.UsbService) as Android.Hardware.Usb.UsbManager;
var attached_devices = USB_Manager.DeviceList;
//Find the device in the list of connected devices
foreach (var d in attached_devices.Keys)
{
if (attached_devices[d].VendorId == VendorID && attached_devices[d].ProductId == ProductID)
{
USB_Device = attached_devices[d];
break;
}
}
//Assuming we found the correct device, let's set everything up
if (USB_Device != null)
{
for (int j = 0; j < USB_Device.InterfaceCount; j++)
{
DeviceInterface = USB_Device.GetInterface(j);
for (int i = 0; i < DeviceInterface.EndpointCount; i++)
{
var temp_ep = DeviceInterface.GetEndpoint(i);
if (temp_ep.Type == Android.Hardware.Usb.UsbAddressing.XferInterrupt)
{
if (temp_ep.Direction == Android.Hardware.Usb.UsbAddressing.In)
{
InputEndpoint = temp_ep;
}
if (temp_ep.Direction == Android.Hardware.Usb.UsbAddressing.Out)
{
OutputEndpoint = temp_ep;
}
}
}
}
//Request permission to communicate with this USB device
UsbReceiver receiver = new UsbReceiver();
PendingIntent pending_intent = PendingIntent.GetBroadcast(Game.Activity, 0, new Android.Content.Intent(UsbReceiver.ACTION_USB_PERMISSION), 0);
IntentFilter intent_filter = new IntentFilter(UsbReceiver.ACTION_USB_PERMISSION);
Game.Activity.RegisterReceiver(receiver, intent_filter);
USB_Manager.RequestPermission(USB_Device, pending_intent);
bool has_permission = USB_Manager.HasPermission(USB_Device);
var device_connection = USB_Manager.OpenDevice(USB_Device);
device_connection.ClaimInterface(DeviceInterface, true);
DeviceConnection = device_connection;
}
Next, here is how I attempt to read from the device:
//3 methods of attempting to read from the device
//Method 1:
byte[] inpt = new byte[64];
var request = new UsbRequest();
request.Initialize(DeviceConnection, InputEndpoint);
var byte_buffer = ByteBuffer.Allocate(64);
request.Queue(byte_buffer, 64);
DeviceConnection.RequestWait();
byte_buffer.Rewind();
for(int i = 0; i < 64; i++)
{
inpt[i] = (byte) byte_buffer.Get();
}
//Method 2:
byte[] inpt = new byte[64];
DeviceConnection.BulkTransfer(InputEndpoint, inpt, inpt.Length, 1000);
//Method 3:
byte[] inpt = new byte[64];
DeviceConnection.ControlTransfer(UsbAddressing.In, 0, 0, 0, inpt, 64, 1000);
And finally, here is how I attempt to write data to this device:
//Method 1:
byte[] output_msg; //This variable is assigned elsewhere in the code
DeviceConnection.BulkTransfer(OutputEndpoint, output_msg, output_msg.Length, 30);
//Method 2:
byte[] output_msg; //This variable is assigned elsewhere in the code
DeviceConnection.ControlTransfer(UsbAddressing.Out, 0, 0, 0, output_msg, output_msg.Length, 1000);
//Method 3:
byte[] output_msg; //This variable is assigned elsewhere in the code
var write_request = new UsbRequest();
write_request.Initialize(DeviceConnection, OutputEndpoint);
var byte_buffer_write = ByteBuffer.Wrap(output_msg);
request.Queue(byte_buffer_write, output_msg.Length);
DeviceConnection.RequestWait();
"OutputEndpoint" is typically null because there is no output endpoint, so I often replace "OutputEndpoint" with "InputEndpoint", but with no success.
Any help would be greatly appreciated! Thanks!!!
You are dealing with HID devices which means you should do Interrupt Transfers.
In Android, you should use UsbRequest to perform Interrupt Transfers (as it does Asynchronous NonBlocking IO).
The endpoints are unidirectional and can be used for both inbounds and outbound (but not at the same time)
If the endpoint is inbound then submit the Urb using UsbRequest and queue as you tried before but using empty buffer with expected bufferLength.
The RequestWait will return UsbRequest Object back upon completion.
If the usbRequest.getEndPoint().getDirection() is inbound then your buffer variable will be updated with read buffer from the device.
If the usbRequest.getEndpoint().getDirection() is outbound then you should pass your buffer to write data to the device

Bluetooth C# using 32feet.net to connect to a speaker

I am currently trying use 32feet.net to connect to a bluetooth speaker that once shutdown (the computer or the speaker) they stay paired but they dont auto reconnect. Therefore I want to make an windows service that tries to reconnect to it every so often if its not connected and if it can find it.
I have tried
C# 32feet.Net: Handling two bluetooth connections in seperate threads, gives SocketException
Code but for some reason there is a few things that light up red.
I am also trying to figure out and make this code work at the same time for the same purpose
public void btconnect()
{
List<Device> devices = new List<Device>();
InTheHand.Net.Sockets.BluetoothClient bc = new InTheHand.Net.Sockets.BluetoothClient();
InTheHand.Net.Sockets.BluetoothDeviceInfo[] array = bc.DiscoverDevices();
int count = array.Length;
for (int i = 0; i<count; i++)
{
Device device = new Device(array[i]);
devices.Add(device);
}
foreach(Device d in devices)
{
if (d.DeviceInfo.ToString().Equals("myphonesdevicenumber"))
{
Guid MyServiceUuid
= new Guid("{00112233-4455-6677-8899-aabbccddeeff}"); // found this somewhere not sure what the string represents.
byte[] guidbytearray = d.DeviceInfo.ToByteArray(); // guid as a byte array.
string guidstring = d.DeviceInfo.ToString(); //guid as a string.
Int64 guid64 = d.DeviceInfo.ToInt64(); // guid as an int64.
Guid g = new Guid(guidbytearray);
bc.Connect(d.DeviceInfo,MyServiceUuid);
// turnoff = false;
}
}
}
List devices = new List();
in the orignal code this wasnt there and I dont know if he was using (Device) it from a external reference or not.
In the article of 32feet, they list an inner-class named Device. You should use it in your program.
The Guid is the identifier for the socket used to connect to your BT device.
The format is a 32 digit long of hex numbers divided into group of 8, 4 ,4 ,4 and 12. Between the groups there is a '-'.

LibUsbDotNet UsbDevice.ControlTransfer hangs

I have a C# .Net Winforms application, which uses LibUsbDotNet to program firmware into an USB-device (Atmel AVR32) using "DFU_DNLOAD" transfers, which is a special kind of control-transfers. This all works, BUT: A specific kind of transfer, which causes the device to erase its internal flash, fails to send an ACK within the correct timing.
When this happens, my LibUsbDotNet connection becomes irreparably broken, which causes everything to fail.
My code does the following:
int TransferToDevice(byte request, short value, byte[] data)
{
var setup = new UsbSetupPacket(
(byte)(UsbCtrlFlags.Direction_Out | UsbCtrlFlags.RequestType_Class | UsbCtrlFlags.Recipient_Interface),
request,
value,
0,
(short)data.Length);
int n;
IntPtr unmanagedPointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(data.Length);
System.Runtime.InteropServices.Marshal.Copy(data, 0, unmanagedPointer, data.Length);
// UsbDevice obtained else-where
if (!UsbDevice.ControlTransfer(ref setup, unmanagedPointer, data.Length, out n))
{
n = 0;
}
System.Runtime.InteropServices.Marshal.FreeHGlobal(unmanagedPointer);
return n;
}
// In order to do a "DFU_DNLOAD", the method above is used as follows:
TransferToDevice(DFU_DNLOAD, Transactions++, data); // "data" is the payload
// where DFU_DNLOAD is:
private const byte DFU_DNLOAD = 1;
// Transactions is
short Transaction = 0;
The above code works (the device correctly receives the "DFU_DNLOAD" message), but the missing ACK is the problem. Once the error occurs, every attempt to communicate with the device (even if I try to re-initialize everything) fails, untill the device is disconnected and re-inserted...
I would like to be able to reset or re-initialize the USB-connection somehow, when this error occurs. Currently I am only able to re-establish communications with the device by exiting my application and re-starting it manually.
This was never solved to my satisfaction, ended up implementing my own "DFU" protocol ontop of LibUSB using plain C, and P/Invoke to that, avoiding LibUsbDotNet entirely... This solution seems to work.
Just guessing, but in case if data is array of short, than size of the buffer should be adjusted
int numberOfValues = data.Length;
int size = Marshal.SizeOf(typeof(short));
IntPtr unmanagedPointer = Marshal.AllocHGlobal(numberOfValues*size);
if (unmanagedPointer == IntPtr.Zero)
throw new OutOfMemoryException("Unable allocate memory");

How to detect Windows Mobile 5 Device Serial Number? (.NET CF 3.5)

We have several devices where I work (mostly Datalogic 4420 Falcon), and someone is always leaving one off the base. The battery runs dry, then they bring them back to get setup all over. (There's supposed to be a way to configure a file on the SD card to reload upon such an error, but it doesn't work very well)
When someone saves changes on the device (using my app that writes data to the SQL Server), the Serial Number is sent along with it so we can track what devices are in use where.
Each device has a Serial Number, and I have to physically (i.e. manually) write that into the Device name field, which I can read. Working code here if anyone wants to know how:
static string deviceId = null;
public static string DeviceName {
get {
if (String.IsNullOrEmpty(deviceId)) {
using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Ident", true)) {
try {
deviceId = key.GetValue("Name", "[Unnamed]").ToString();
} catch (Exception e) {
ErrorWrapper("GetDeviceName", e);
deviceId = Dns.GetHostName();
} finally {
key.Flush();
key.Close();
}
}
}
return deviceId;
}
}
I do not like the manual (i.e. Fat Finger prone) Serial Number entry. Is there some call to query the device's Serial Number, or is that vendor specific?
Datamax does make an SDK that is specific to their devices, but we don't want our applications tied down to any one manufacturer (we are already tied down to VS2008).
I'd start by trying to P/Invoke to get the device ID (KerneIoControl with IOCTL_HAL_GET_DEVICEID) and see if it matches the serial number you're after. Here's an example.
I don't know about your Datalogic 4420 Falcon device, but I work with Intermec CK30 & CK60 and I have their itc50.dll file.
Here is snippet:
[DllImport("itc50.dll")]public static extern int ITCGetSerialNumber(StringBuilder Snumber, int buffSize);
StringBuilder hwSN = new StringBuilder(12);
if (ITCGetSerialNumber(hwSN, hwSN.Capacity) >= 0)
{
;
;
}

detecting presence of bluetooth printer

I'm working on a mobile application (C#/WPF on a tablet PC) that prints to a bluetooth connected printer. Right now I just fire off a print job, and if the printer is not present the printer subsystem reports an error to the user. I'm not doing anything programatically with Bluetooth, just using PrintDialog().
I'd like to modify this process to detect the printer first - if it is not available, then I'll just store the document without printing. Is there a way in code for me to detect if the bluetooth device is connected/active/available?
If I look at the device in the Bluetooth panel under Control Panel, it doesn't seem to have any sort of status that reflects whether or not the device is available, so maybe this isn't possible.
I'm assuming the printer has already been setup and configured in Windows - all I need to do is detect if it is actually present at a given point in time.
Perhaps use the 32feet.NET library (of which I am the maintainer) and check if the printer is present before submitting the job. You'd need to know the Bluetooth address of the printer; can one get that from the system, or maybe you always know it.
Discovery on the MSFT Bluetooth stack always returns all known devices in amongst those in range :-( but we can use other means to detect the device's presence/absence. Perhaps using BluetoothDeviceInfo.GetServiceRecords in its BeginGetServiceRecords form. e.g. something like (not tested/compiled):
bool IsPresent(BluetoothAddress addr) // address from config somehow
{
BluetoothDeviceInfo bdi = new BluetoothDeviceInfo(addr);
if (bdi.Connected) {
return true;
}
Guid arbitraryClass = BluetoothService.Headset;
AsyncResult<bool> ourAr = new AsyncResult<bool>(); // Jeffrey Richter's impl
IAsyncResult ar = bdi.BeginGetService(arbitraryClass, IsPresent_GsrCallback, ourAr);
bool signalled = ourAr.AsyncWaitHandle.WaitOne(Timeout);
if (!signalled) {
return false; // Taken too long, so not in range
} else {
return ourAr.Result;
}
}
void IsPresent_GsrCallback(IAsyncResult ar)
{
AsyncResult<bool> ourAr = (AsyncResult<bool>)ar.AsyncState;
const bool IsInRange = true;
const bool completedSyncFalse = true;
try {
bdi.EndGetServiceResult(ar);
ourAr.SetAsCompleted(IsInRange, completedSyncFalse);
} catch {
// If this returns quickly, then it is in range and
// if slowly then out of range but caller will have
// moved on by then... So set true in both cases...
// TODO check what error codes we get here. SocketException(10108) iirc
ourAr.SetAsCompleted(IsInrange, completedSyncFalse);
}
}

Categories

Resources