Example #1
0
        public void connect()
        {
            byte[] connect_request = new byte[REPORTSIZE];
            byte[] response        = new byte[REPORTSIZE];
            connect_request[2] = (byte)(connect_request[2] | BYTE2_CONNECT_BIT);
            bool connected = false;

            while (!connected)
            {
                //wait till connect bit is received on a request with connect bit set
                HIDout.Write(connect_request, 0, REPORTSIZE);
                Console.WriteLine("Connect request sent");

                HIDin.Read(response, 0, REPORTSIZE);
                byte SEQ         = (byte)(response[2] & BITMASK);
                bool CONNECT_BIT = (response[2] & BYTE2_CONNECT_BIT) != 0;

                if (CONNECT_BIT)
                {
                    connect_request[2] = (byte)(connect_request[2] | SEQ);  // set ACK to SEQ and infor sender that we are in sync by sending correct ACK
                    HIDout.Write(connect_request, 0, REPORTSIZE);

                    //update the start seq number (this is all this handshake is about)
                    state_last_valid_seq_received = SEQ;
                    connected = true;
                }
                else
                {
                    print_debug(String.Format("SEQ {0} received on connect, but no connect response", SEQ));
                }
            }

            this.state_connected            = true;
            this.state_invalid_seq_received = false;
        }
Example #2
0
        private void HIDOutThreadLoop()
        {
            //int PAYLOAD_MAX_INDEX = PAYLOAD_MAX_SIZE - 1;

            byte BYTE1_RESEND_BIT = 1 << 6;



            Console.WriteLine("Starting write loop continously sending HID ouput report");

            List <byte> current_stream = new List <byte>(); //represents the remainder of the stream (from upper layer), which is currently processed (splitted into chunks, capable of being sent via HID report)
            List <byte> report_payload;                     //represents the payload which gets sent in a single report

            while (true)
            {
                bool last_report_of_stream = true; //if this bit is set, this means the report is the last one in a fragemented STREAM

                //check if there isn't a stream which hasn't been fully sent (remaining chunks in current_stream)
                if (current_stream.Count == 0)
                {
                    // no pending data in current stream, check if new full length stream is waiting in out queue
                    if (this.state_report_out_queue.Count > 0)
                    {
                        //dequeue next stream and put it into current_stream
                        current_stream.AddRange(PopOutputStream()); //type casting to byte array needed, as this isn't a generic Queue of type byte[] (synchronization wouldn't be possible)
                    }
                }

                //check if stream is small enough to fit into a single report
                if (current_stream.Count > PAYLOAD_MAX_SIZE)
                {
                    //no
                    report_payload = current_stream.GetRange(0, PAYLOAD_MAX_SIZE); //fetch MAX_SIZE bytes from the beginning
                    current_stream.RemoveRange(0, PAYLOAD_MAX_SIZE);               //remove fetched bytes
                }
                else
                {
                    report_payload = current_stream.GetRange(0, current_stream.Count); //put the rest of the stream into payload
                    current_stream.Clear();                                            //empty out current_stream
                }

                //if remaining data in current stream, set FIN bit to false
                if (current_stream.Count > 0)
                {
                    last_report_of_stream = false;
                }

                /*
                 * Create the final report which should be send
                 */

                //if (report_payload.Count < 62 && report_payload.Count > 0) Console.WriteLine(String.Format("Output report with payload size {0} written",  report_payload.Count));

                //create LEN_FIN byte
                byte BYTE1_LEN_FLAGS = (byte)(report_payload.Count & BITMASK);
                if (last_report_of_stream)
                {
                    BYTE1_LEN_FLAGS += BYTE1_FIN_BIT;
                }

                byte BYTE2_ACK = state_last_valid_seq_received; // set ACK byte to the last valid sequence received

                //set resend request bit, if last SEQ received was invalid
                if (state_invalid_seq_received)
                {
                    BYTE1_LEN_FLAGS += BYTE1_RESEND_BIT; // set RESEND BIT in byte1
                    BYTE2_ACK       += 1;                //increase the ACK by one (las valid SEQ + 1 is the next needed SEQ)
                    if (BYTE2_ACK > MAX_SEQ)
                    {
                        BYTE2_ACK -= MAX_SEQ;
                    }
                }

                //prepend head to report (first byte is always 0, as it represents the unused HID report ID)
                report_payload.InsertRange(0, new byte[] { 0, BYTE1_LEN_FLAGS, BYTE2_ACK });
                byte[] report = new byte[REPORTSIZE];
                report_payload.CopyTo(report);

                /*
                 * Write report to HID device
                 */
                HIDout.Write(report, 0, REPORTSIZE);
            }
        }