Skip to content

Writing To and Reading From a Device

Christian Findlay edited this page Dec 30, 2018 · 12 revisions

Usb.Net and Hid.Net are designed to be used in a similar fashion to the Request/Response pattern.

Not all devices fit this pattern so theses libraries won't fit all scenarios. For example, these libraries would suit the scenario of creating a mouse driver. A mouse driver's feedback is driven by the user's physical movement of the mouse. The device will send data to the computer in an ad hoc way. These libraries are generally designed for cases where you want to send some data to the device, and then have some data returned to the computer.

The libraries expect you to send data in the form of an array of bytes, and another array of bytes will be returned. Generally speaking, the device will expect an array of 64 bytes, or a higher number if the device is designed for high speed transfer. If you need to send more data to the device than the largest size the device will accept, you will need to break it up in to smaller chunks. Most devices will support this, but you will need to see the device's specific documentation for this. You can check the max size of the array in the WriteBufferSize, and ReadBufferSize properties of DeviceDefinition for the device. The definition can be found on any class that inherits from DeviceBase.

To write data, call the WriteAndReadAsync method with your array of data. If the class inherits from DeviceBase, the method will be thread safe. You can safely call it and processing will occur in order. It should happen in a first in, first out fashion. If you use the WriteAsync, or ReadAsync methods, thread safety is not guaranteed.

Seeing that data is all written in binary, you will probably be required to serialize or deserialize the data in some way. Google's Protocol Buffers protocol is a good protocol for converting data to objects, and converting objects to data. Satoshi Labs implemented this protocol for their devices. Here is an example of how objects can be converted to data arrays, and vice versa:

This code takes an object of a known type, and converts it a data array before sending it to the device:

    private async Task WriteAsync(object msg)
        {
            Logger.Log($"Write: {msg}", null, LogSection);

            var byteArray = Serialize(msg);

            //This confirms that the message data is correct
            // var testMessage = Deserialize(msg.GetType(), byteArray);

            var msgSize = byteArray.Length;
            var msgName = msg.GetType().Name;

            var messageTypeString = "MessageType" + msgName;

            var messageType = GetEnumValue(messageTypeString);

            var msgId = (int)messageType;
            var data = new ByteBuffer(msgSize + 1024); // 32768);
            data.Put((byte)'#');
            data.Put((byte)'#');
            data.Put((byte)((msgId >> 8) & 0xFF));
            data.Put((byte)(msgId & 0xFF));
            data.Put((byte)((msgSize >> 24) & 0xFF));
            data.Put((byte)((msgSize >> 16) & 0xFF));
            data.Put((byte)((msgSize >> 8) & 0xFF));
            data.Put((byte)(msgSize & 0xFF));
            data.Put(byteArray);

            while (data.Position % 63 > 0)
            {
                data.Put(0);
            }

            var chunks = data.Position / 63;

            var wholeArray = data.ToArray();

            for (var i = 0; i < chunks; i++)
            {
                var range = new byte[64];
                range[0] = (byte)'?';

                for (var x = 0; x < 63; x++)
                {
                    range[x + 1] = wholeArray[(i * 63) + x];
                }

                await Device.WriteAsync(range);
            }

            _LastWrittenMessage = msg;
    }

Code Reference

Clone this wiki locally