View Single Post
  #36  
Old 10-04-2013, 10:49 AM
Thatualle1970's Avatar
Thatualle1970 Thatualle1970 is offline
Registered User
Thatualle1970's PC Specs
 
Join Date: Sep 2013
Location: Dorchester, ON
Posts: 17
POST ID # = 677168
Thatualle1970 Reputation: 13
Default

Quote:
Originally Posted by bobpombrio View Post
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...
Reply With Quote


1 members found this post helpful.