Quote:
Originally Posted by bobpombrio
Can some one tell me the USB vendor ID and the USB product ID for the H100i? Like you I am not happy with the Link software and I'd like to write my own. I see all of this great work has been done that explains the protocol and I'd like to take advantage of it.
|
PID is always 0x1B1C
VID is 0x0C04 for H80i and H100i
VID is 0x0C02 for the USB Commander
They use the same basic protocol, except the Commander's don't have the extra length byte at the very beginning. Here's what I have working so far (C# code, this depends on HidLibrary which you can get from NuGet):
Code:
public List<Int32> ListPorts() {
int packetIndex = 1; // skip the report id field (always zero)
byte[] packet = new byte[65]; // size of the packet plus report id
if (newProtocol) packet[packetIndex++] = 2; // newProtocol = (pid == 0xC04)
packet[packetIndex++] = (byte)index; // write the index
if (index < 255) index++; else index = 20; // and cycle it
packet[packetIndex++] = 0x4F; // command to get the port status
// perform the io
device.Write(packet, 500);
var inpacket = device.Read(500);
// and collect our list of active channels
List<Int32> ports = new List<Int32>();
for (int portIndex = 0; portIndex < 8; portIndex++) {
// any port set to 0xFF is not present, anything else is 'live'
if (inpacket.Data[3 + portIndex] != 0xFF)
ports.Add(portIndex);
}
return ports;
}
Code:
// reportid, length, index, command, register, len
// 0 1 2 3 4 5 <- block
// 0 1 2 3 4 <- byte/word
// ^-- omitted with old USB Commander (0xC02)
// reportid, index, command/status, data...
// 0 1 2 3
// ^-- omitted with USB Commander
public byte[] ReadData(int reg, int len = 1) {
int i = (newProtocol) ? 2 : 1; // fill in the length when we're done
byte[] packet = new byte[65]; // our standard packet length
int command = (Port << 4) | 1; // port fills the high nibble, 1 is 'read'
if (len == 1) command |= 6; // read byte
else if (len == 2) command |= 8; // read short
else command |= 10; // read any length
packet[i++] = (byte)index; // obligatory index field
if (index < 255) index++; else index = 20; // and cycle
packet[i++] = (byte)command; // command byte
packet[i++] = (byte)reg; // the register we'd like to read
if (len > 2) packet[i++] = (byte)len; // arbitrary length require the length
if (newProtocol) packet[1] = (byte)(index - 1); // add in our total length
// do the io
device.Write(packet, 500);
var inpacket = device.Read(500);
if (inpacket != null && inpacket.Status == HidDeviceData.ReadStatus.Success) {
// ignore bad packets (handle the null from the caller side)
if (inpacket.Data[1] != packet[(newProtocol) ? 2 : 1]) return null;
if ((inpacket.Data[2] & 240) != 0) return null;
// grab our returned data from within the packet
byte[] data = new byte[len];
Buffer.BlockCopy(inpacket.Data, 3, data, 0, len);
return data;
}
else return null;
}
Code:
// reportid, length, index, command, register, len, data...
// 0 1 2 3 4 5, 6... <- block
// 0 1 2 3 4 5... <- byte/word
// ^-- omitted with USB Commander (0xC02)
public bool WriteData(int reg, byte[] data) {
int i = (newProtocol) ? 2 : 1; // fill in the length when we're done
byte[] packet = new byte[65]; // our standard packet length
int command = (Port << 4); // port fills the high nibble, no low bit for write
if (data.Length == 1) command |= 6; // byte
else if (data.Length == 2) command |= 8; // short
else command |= 10; // arbitrary length
packet[i++] = (byte)index; // index and cycle
if (index < 255) index++; else index = 20;
packet[i++] = (byte)command; // command field
packet[i++] = (byte)reg; // register we're writing too
if (data.Length > 2) packet[i++] = (byte)(data.Length); // length, if req'd
Buffer.BlockCopy(data, 0, packet, i, data.Length); // data we're writing
i += data.Length; // position in the packet
if (newProtocol) packet[1] = (byte)(index - 1); // prefix packet length
device.Write(packet, 500); // do the io
var inpacket = device.Read(500);
// return true if the write was successful
return (inpacket != null && inpacket.Status == HidDeviceData.ReadStatus.Success);
}
From here you need to just enumerate everything and push that info up to some sort of UI. It's important that you not try to talk to the same device using multiple threads, that breaks things, so either stick to single threading, single threading per USB device, or use locks to ensure that the write-read sequence is always unbroken.
Apologies for the messy code.
The code is very "C" like and should be easy enough to port to Linux (unless mono can be made to work), but that's beyond my realm of expertise...