Example #1
0
        protected override void _OUTTransaction(USBTransfer transfer, USBTransaction uTransaction, bool toggle, void *buffer, ushort length)
        {
#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: OUT Transaction");
            BasicConsole.DelayOutput(5);
#endif

            UHCITransaction uT = new UHCITransaction();
            uTransaction.underlyingTz = uT;
            uT.inBuffer = null;
            uT.inLength = 0;

            uT.qTD       = CreateQTD_IO((UHCI_QueueHead_Struct *)transfer.underlyingTransferData, (uint *)1, UHCI_Consts.TD_OUT, toggle, length, transfer.device.address, transfer.endpoint, transfer.packetSize);
            uT.qTDBuffer = uT.qTD->virtBuffer;

            if (buffer != null && length != 0)
            {
                MemoryUtils.MemCpy_32((byte *)uT.qTDBuffer, (byte *)buffer, length);
            }

            if (transfer.transactions.Count > 0)
            {
                UHCITransaction uLastTransaction = (UHCITransaction)((USBTransaction)(transfer.transactions[transfer.transactions.Count - 1])).underlyingTz;
                uLastTransaction.qTD->next   = (((uint)VirtMemManager.GetPhysicalAddress(uT.qTD) & 0xFFFFFFF0) | UHCI_Consts.BIT_Vf); // build TD queue
                uLastTransaction.qTD->q_next = uT.qTD;
            }
        }
Example #2
0
        /// <summary>
        /// Sets up an OUT transaction and adds it to the specified transfer.
        /// </summary>
        /// <param name="transfer">The transfer to which the transaction should be added.</param>
        /// <param name="controlHandshake">Whether the transaction is part of a control handshake or not.</param>
        /// <param name="buffer">The buffer of outgoing data.</param>
        /// <param name="length">The length of the buffer.</param>
        public void OUTTransaction(USBTransfer transfer, bool controlHandshake, void *buffer, ushort length)
        {
            ushort clampedLength = FOS_System.Math.Min(transfer.packetSize, length);

            length -= clampedLength;
            ushort remainingTransactions = (ushort)(length / transfer.packetSize);

            if (length % transfer.packetSize != 0)
            {
                remainingTransactions++;
            }

            USBTransaction transaction = new USBTransaction();

            transaction.type = USBTransactionType.OUT;

            if (controlHandshake) // Handshake transaction of control transfers always have toggle set to 1
            {
                ((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle = true;
            }

            _OUTTransaction(transfer, transaction, ((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle, buffer, clampedLength);

            transfer.transactions.Add(transaction);

            ((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle = !((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle; // Switch toggle

            if (remainingTransactions > 0)
            {
                OUTTransaction(transfer, controlHandshake, ((byte *)buffer + clampedLength), length);
            }
        }
Example #3
0
        /// <summary>
        /// Sets up a SETUP transaction and adds it to the specified transfer.
        /// </summary>
        /// <param name="transfer">The transfer to which the transaction should be added.</param>
        /// <param name="tokenBytes">The number of bytes to send.</param>
        /// <param name="type">The type of the USB Request.</param>
        /// <param name="req">The specific USB Request.</param>
        /// <param name="hiVal">The USB Request Hi-Val.</param>
        /// <param name="loVal">The USB Request Lo-Val.</param>
        /// <param name="index">The USB request index.</param>
        /// <param name="length">The length of the USB request.</param>
        public void SETUPTransaction(USBTransfer transfer, ushort tokenBytes, byte type, byte req, byte hiVal, byte loVal,
                                     ushort index, ushort length)
        {
            USBTransaction transaction = new USBTransaction();

            transaction.type = USBTransactionType.SETUP;

            _SETUPTransaction(transfer, transaction, false, tokenBytes, type, req, hiVal, loVal, index, length);

            transfer.transactions.Add(transaction);

            ((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle = true;
        }
Example #4
0
        /// <summary>
        /// Sets up an IN transaction and adds it to the specified transfer.
        /// </summary>
        /// <param name="transfer">The transfer to which the transaction should be added.</param>
        /// <param name="controlHandshake">Whether the transaction is part of a control handshake or not.</param>
        /// <param name="buffer">The buffer to store the incoming data in.</param>
        /// <param name="length">The length of the buffer.</param>
        public void INTransaction(USBTransfer transfer, bool controlHandshake, void *buffer, ushort length)
        {
#if HCI_TRACE || USB_TRACE
            BasicConsole.WriteLine(((FOS_System.String) "transfer.packetSize=") + transfer.packetSize +
                                   ", length=" + length);
#endif
            ushort clampedLength = FOS_System.Math.Min(transfer.packetSize, length);
            length -= clampedLength;
#if HCI_TRACE || USB_TRACE
            BasicConsole.WriteLine(((FOS_System.String) "clampedLength=") + clampedLength);
            BasicConsole.DelayOutput(1);
#endif
            ushort remainingTransactions = (ushort)(length / transfer.packetSize);
#if HCI_TRACE || USB_TRACE
            BasicConsole.WriteLine("Division passed.");
            BasicConsole.DelayOutput(1);
#endif
            if (length % transfer.packetSize != 0)
            {
                remainingTransactions++;
            }

            USBTransaction transaction = new USBTransaction();
            transaction.type = USBTransactionType.IN;

            if (controlHandshake) // Handshake transaction of control transfers always have toggle set to 1
            {
                ((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle = true;
            }

#if HCI_TRACE
            BasicConsole.WriteLine("Call _INTransaction...");
            BasicConsole.DelayOutput(1);
#endif

            _INTransaction(transfer, transaction, ((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle, buffer, clampedLength);

#if HCI_TRACE
            BasicConsole.WriteLine("Done.");
            BasicConsole.DelayOutput(1);
#endif

            transfer.transactions.Add(transaction);

            ((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle = !((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle; // Switch toggle

            if (remainingTransactions > 0)
            {
                INTransaction(transfer, controlHandshake, ((byte *)buffer + clampedLength), length);
            }
        }
Example #5
0
        protected override void _SETUPTransaction(USBTransfer transfer, USBTransaction uTransaction, bool toggle, ushort tokenBytes, byte type, byte req, byte hiVal, byte loVal, ushort index, ushort length)
        {
#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: SETUP Transaction");
            BasicConsole.DelayOutput(5);
#endif

            UHCITransaction uT = new UHCITransaction();
            uTransaction.underlyingTz = uT;
            uT.inBuffer = null;
            uT.inLength = 0;

            uT.qTD       = CreateQTD_SETUP((UHCI_QueueHead_Struct *)transfer.underlyingTransferData, (uint *)1, toggle, tokenBytes, type, req, hiVal, loVal, index, length, transfer.device.address, transfer.endpoint, transfer.packetSize);
            uT.qTDBuffer = uT.qTD->virtBuffer;

            if (transfer.transactions.Count > 0)
            {
                UHCITransaction uLastTransaction = (UHCITransaction)((USBTransaction)(transfer.transactions[transfer.transactions.Count - 1])).underlyingTz;
                uLastTransaction.qTD->next   = (((uint)VirtMemManager.GetPhysicalAddress(uT.qTD) & 0xFFFFFFF0) | UHCI_Consts.BIT_Vf); // build TD queue
                uLastTransaction.qTD->q_next = uT.qTD;
            }
        }
Example #6
0
 /// <summary>
 /// Sets up a SETUP transaction and adds it to the specified transfer.
 /// </summary>
 /// <param name="transfer">The transfer to which the transaction should be added.</param>
 /// <param name="uTransaction">The USB Transaction to convert to an EHCI Transaction.</param>
 /// <param name="toggle">The transaction toggle state.</param>
 /// <param name="tokenBytes">The number of bytes to send.</param>
 /// <param name="type">The type of the USB Request.</param>
 /// <param name="req">The specific USB Request.</param>
 /// <param name="hiVal">The USB Request Hi-Val.</param>
 /// <param name="loVal">The USB Request Lo-Val.</param>
 /// <param name="index">The USB request index.</param>
 /// <param name="length">The length of the USB request.</param>
 protected override void _SETUPTransaction(USBTransfer transfer, USBTransaction uTransaction, bool toggle, ushort tokenBytes,
                                           byte type, byte req, byte hiVal, byte loVal, ushort index, ushort length)
 {
     // Create an EHCI-specific object to describe the transaction
     EHCITransaction eTransaction = new EHCITransaction();
     // Store the underlying HC-specific transaction info
     uTransaction.underlyingTz = eTransaction;
     // SETUP transaction so there is no input buffer
     eTransaction.inBuffer = null;
     eTransaction.inLength = 0u;
     // Create and initialise the SETUP queue transfer descriptor
     eTransaction.qTD = CreateQTD_SETUP(null, toggle, tokenBytes, type, req, hiVal, loVal, index, length);
     
     // If the number of existing transactions is greater than 0
     //  i.e. some transactions have already been added.
     if (transfer.transactions.Count > 0)
     {
         // Get the previous (i.e. last) transaction then the underlying transaction from it
         EHCITransaction eLastTransaction = (EHCITransaction)((USBTransaction)(transfer.transactions[transfer.transactions.Count - 1])).underlyingTz;
         // Create a wrapper for the last transaction (qTD)
         EHCI_qTD lastQTD = eLastTransaction.qTD;
         // Set the Next Transaction (qTD) Pointer on the previous qTD to point to the qTD
         //  we just created. 
         // Note: The NextqTDPointer must be the physical address of qTD data.
         lastQTD.NextqTDPointer = (EHCI_qTD_Struct*)VirtMemManager.GetPhysicalAddress(eTransaction.qTD.qtd);
         // Mark the previous qTD's Next Transaction Pointer as valid.
         lastQTD.NextqTDPointerTerminate = false;
     }
 }
Example #7
0
        protected override void _OUTTransaction(USBTransfer transfer, USBTransaction uTransaction, bool toggle, void* buffer, ushort length)
        {
#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: OUT Transaction");
            BasicConsole.DelayOutput(5);
#endif

            UHCITransaction uT = new UHCITransaction();
            uTransaction.underlyingTz = uT;
            uT.inBuffer = null;
            uT.inLength = 0;

            uT.qTD = CreateQTD_IO((UHCI_QueueHead_Struct*)transfer.underlyingTransferData, (uint*)1, UHCI_Consts.TD_OUT, toggle, length, transfer.device.address, transfer.endpoint, transfer.packetSize);
            uT.qTDBuffer = uT.qTD->virtBuffer;

            if (buffer != null && length != 0)
            {
                MemoryUtils.MemCpy_32((byte*)uT.qTDBuffer, (byte*)buffer, length);
            }

            if (transfer.transactions.Count > 0)
            {
                UHCITransaction uLastTransaction = (UHCITransaction)((USBTransaction)(transfer.transactions[transfer.transactions.Count - 1])).underlyingTz;
                uLastTransaction.qTD->next = (((uint)VirtMemManager.GetPhysicalAddress(uT.qTD) & 0xFFFFFFF0) | UHCI_Consts.BIT_Vf); // build TD queue
                uLastTransaction.qTD->q_next = uT.qTD;
            }
        }
Example #8
0
        protected override void _SETUPTransaction(USBTransfer transfer, USBTransaction uTransaction, bool toggle, ushort tokenBytes, byte type, byte req, byte hiVal, byte loVal, ushort index, ushort length)
        {
#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: SETUP Transaction");
            BasicConsole.DelayOutput(5);
#endif

            UHCITransaction uT = new UHCITransaction();
            uTransaction.underlyingTz = uT;
            uT.inBuffer = null;
            uT.inLength = 0;

            uT.qTD = CreateQTD_SETUP((UHCI_QueueHead_Struct*)transfer.underlyingTransferData, (uint*)1, toggle, tokenBytes, type, req, hiVal, loVal, index, length, transfer.device.address, transfer.endpoint, transfer.packetSize);
            uT.qTDBuffer = uT.qTD->virtBuffer;

            if (transfer.transactions.Count > 0)
            {
                UHCITransaction uLastTransaction = (UHCITransaction)((USBTransaction)(transfer.transactions[transfer.transactions.Count - 1])).underlyingTz;
                uLastTransaction.qTD->next = (((uint)VirtMemManager.GetPhysicalAddress(uT.qTD) & 0xFFFFFFF0) | UHCI_Consts.BIT_Vf); // build TD queue
                uLastTransaction.qTD->q_next = uT.qTD;
            }
        }
Example #9
0
        protected override void _IssueTransfer(USBTransfer transfer)
        {
#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Issue Transfer");
            BasicConsole.DelayOutput(5);
#endif

            UHCITransaction firstTransaction = (UHCITransaction)((USBTransaction)transfer.transactions[0]).underlyingTz;
            UHCITransaction lastTransaction  = (UHCITransaction)((USBTransaction)transfer.transactions[transfer.transactions.Count - 1]).underlyingTz;
            UHCI_qTD.SetIntOnComplete(lastTransaction.qTD, true);  // We want an interrupt after complete transfer
            CreateQH((UHCI_QueueHead_Struct *)transfer.underlyingTransferData, (uint)transfer.underlyingTransferData, firstTransaction.qTD);

#if UHCI_TRACE
            BasicConsole.WriteLine("    Queue head data:");
            BasicConsole.DumpMemory(transfer.underlyingTransferData, sizeof(UHCI_QueueHead_Struct));
            BasicConsole.WriteLine("    Transactions data:");
            for (int i = 0; i < transfer.transactions.Count; i++)
            {
                BasicConsole.Write(" ");
                BasicConsole.Write(i);
                BasicConsole.WriteLine(" : ");
                BasicConsole.WriteLine("  - qTD:");
                BasicConsole.DumpMemory(
                    ((UHCITransaction)((USBTransaction)transfer.transactions[i]).underlyingTz).qTD, sizeof(UHCI_qTD_Struct));
                BasicConsole.WriteLine("  - qTDBuffer:");
                BasicConsole.DumpMemory(
                    ((UHCITransaction)((USBTransaction)transfer.transactions[i]).underlyingTz).qTDBuffer, 16);
            }
            BasicConsole.DelayOutput(60);

            BasicConsole.WriteLine("UHCI: Issuing transfer...");
#endif

            for (byte i = 0; i < UHCI_Consts.NUMBER_OF_UHCI_RETRIES && !transfer.success; i++)
            {
                TransactionsCompleted = 0;
                for (int j = 0; j < transfer.transactions.Count; j++)
                {
                    USBTransaction  elem = (USBTransaction)transfer.transactions[j];
                    UHCITransaction uT   = (UHCITransaction)(elem.underlyingTz);
                    uT.qTD->u1 = uT.qTD->u1 & 0xFF00FFFF;
                    UHCI_qTD.SetActive(uT.qTD, true);
                }

                // stop scheduler
                USBSTS.Write_UInt16(UHCI_Consts.STS_MASK);
                USBCMD.Write_UInt16((ushort)(USBCMD.Read_UInt16() & ~UHCI_Consts.CMD_RS));
                while ((USBSTS.Read_UInt16() & UHCI_Consts.STS_HCHALTED) == 0)
                {
                    Hardware.Devices.Timer.Default.Wait(10);
                }

                // update scheduler
                uint qhPhysAddr = ((uint)VirtMemManager.GetPhysicalAddress(transfer.underlyingTransferData) | UHCI_Consts.BIT_QH);
                FrameList[0] = qhPhysAddr;
                FRBASEADD.Write_UInt32((uint)VirtMemManager.GetPhysicalAddress(FrameList));
                FRNUM.Write_UInt16(0);
                // start scheduler
                USBSTS.Write_UInt16(UHCI_Consts.STS_MASK);
                USBCMD.Write_UInt16((ushort)(USBCMD.Read_UInt16() | UHCI_Consts.CMD_RS));
                while ((USBSTS.Read_UInt16() & UHCI_Consts.STS_HCHALTED) != 0)
                {
                    Hardware.Devices.Timer.Default.Wait(10);
                }

#if UHCI_TRACE
                BasicConsole.WriteLine(((FOS_System.String) "USBINT val: ") + USBINTR.Read_UInt16());
#endif

                // run transactions
                bool active  = true;
                int  timeout = 100; //5 seconds
                while (active && timeout > 0)
                {
                    active = false;
                    for (int j = 0; j < transfer.transactions.Count; j++)
                    {
                        USBTransaction  elem = (USBTransaction)transfer.transactions[j];
                        UHCITransaction uT   = (UHCITransaction)(elem.underlyingTz);
                        active = active || ((uT.qTD->u1 & 0x00FF0000) == 0x00800000);
                    }

                    Hardware.Devices.Timer.Default.Wait(50);
                    timeout--;
                }

#if UHCI_TRACE
                BasicConsole.WriteLine("Finished waiting.");
#endif

                FrameList[0] = UHCI_Consts.BIT_T;

                if (timeout == 0 ||
                    TransactionsCompleted != transfer.transactions.Count)
                {
#if UHCI_TRACE
                    BasicConsole.SetTextColour(BasicConsole.error_colour);
                    BasicConsole.WriteLine("UHCI: Error! Transactions wait timed out or wrong number of transactions completed.");
                    BasicConsole.SetTextColour(BasicConsole.default_colour);

                    BasicConsole.WriteLine(((FOS_System.String) "Transactions completed: ") + TransactionsCompleted);

                    if (timeout == 0)
                    {
                        BasicConsole.SetTextColour(BasicConsole.error_colour);
                        BasicConsole.WriteLine("UHCI: Error! Transfer timed out.");
                        BasicConsole.SetTextColour(BasicConsole.default_colour);
                    }
#endif

                    transfer.success = false;

                    bool completeDespiteNoInterrupt = true;
                    for (int j = 0; j < transfer.transactions.Count; j++)
                    {
                        USBTransaction  elem = (USBTransaction)transfer.transactions[j];
                        UHCITransaction uT   = (UHCITransaction)(elem.underlyingTz);

#if UHCI_TRACE
                        BasicConsole.WriteLine(((FOS_System.String) "u1=") + uT.qTD->u1 + ", u2=" + uT.qTD->u2);
                        BasicConsole.WriteLine(((FOS_System.String) "Status=") + (byte)(uT.qTD->u1 >> 16));
#endif
                        completeDespiteNoInterrupt = completeDespiteNoInterrupt && isTransactionSuccessful(uT);
                    }

                    transfer.success = completeDespiteNoInterrupt;

#if UHCI_TRACE
                    BasicConsole.SetTextColour(BasicConsole.warning_colour);
                    BasicConsole.WriteLine(((FOS_System.String) "Complete despite no interrupts: ") + completeDespiteNoInterrupt);
                    BasicConsole.SetTextColour(BasicConsole.default_colour);

                    BasicConsole.DelayOutput(5);
#endif
                }
                else
                {
                    transfer.success = true;
                }

                if (transfer.success)
                {
                    // check conditions and save data
                    for (int j = 0; j < transfer.transactions.Count; j++)
                    {
                        USBTransaction  elem = (USBTransaction)transfer.transactions[j];
                        UHCITransaction uT   = (UHCITransaction)(elem.underlyingTz);
                        transfer.success = transfer.success && isTransactionSuccessful(uT); // executed w/o error

                        if (uT.inBuffer != null && uT.inLength != 0)
                        {
                            MemoryUtils.MemCpy_32((byte *)uT.inBuffer, (byte *)uT.qTDBuffer, uT.inLength);
                        }
                    }
                }

#if UHCI_TRACE
                if (!transfer.success)
                {
                    BasicConsole.SetTextColour(BasicConsole.error_colour);
                    BasicConsole.WriteLine("UHCI: Transfer failed.");
                    BasicConsole.SetTextColour(BasicConsole.default_colour);
                }
                else
                {
                    BasicConsole.SetTextColour((char)0x0200);
                    BasicConsole.WriteLine("Transfer succeeded.");
                    BasicConsole.SetTextColour(BasicConsole.default_colour);
                }
#endif
            }
        }
Example #10
0
        /// <summary>
        /// Sets up an IN transaction and adds it to the specified transfer.
        /// </summary>
        /// <param name="transfer">The transfer to which the transaction should be added.</param>
        /// <param name="controlHandshake">Whether the transaction is part of a control handshake or not.</param>
        /// <param name="buffer">The buffer to store the incoming data in.</param>
        /// <param name="length">The length of the buffer.</param>
        public void INTransaction(USBTransfer transfer, bool controlHandshake, void* buffer, ushort length)
        {
#if HCI_TRACE || USB_TRACE
            BasicConsole.WriteLine(((FOS_System.String)"transfer.packetSize=") + transfer.packetSize +
                                                       ", length=" + length);
#endif
            ushort clampedLength = FOS_System.Math.Min(transfer.packetSize, length);
            length -= clampedLength;
#if HCI_TRACE || USB_TRACE
            BasicConsole.WriteLine(((FOS_System.String)"clampedLength=") + clampedLength);
            BasicConsole.DelayOutput(1);
#endif
            ushort remainingTransactions = (ushort)(length / transfer.packetSize);
#if HCI_TRACE || USB_TRACE
            BasicConsole.WriteLine("Division passed.");
            BasicConsole.DelayOutput(1);
#endif
            if (length % transfer.packetSize != 0)
            {
                remainingTransactions++;
            }

            USBTransaction transaction = new USBTransaction();
            transaction.type = USBTransactionType.IN;

            if (controlHandshake) // Handshake transaction of control transfers always have toggle set to 1
            {
                ((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle = true;
            }

#if HCI_TRACE
            BasicConsole.WriteLine("Call _INTransaction...");
            BasicConsole.DelayOutput(1);
#endif

            _INTransaction(transfer, transaction, ((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle, buffer, clampedLength);

#if HCI_TRACE
            BasicConsole.WriteLine("Done.");
            BasicConsole.DelayOutput(1);
#endif

            transfer.transactions.Add(transaction);

            ((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle = !((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle; // Switch toggle

            if (remainingTransactions > 0)
            {
                INTransaction(transfer, controlHandshake, ((byte*)buffer + clampedLength), length);
            }
        }
Example #11
0
 /// <summary>
 /// When overridden in a derived class, handles HC implementation specific SETUP transaction initialisation.
 /// </summary>
 /// <param name="transfer">The transfer to which the transaction should be added.</param>
 /// <param name="uTransaction">The USB Transaction to convert to an EHCI Transaction.</param>
 /// <param name="toggle">The transaction toggle state.</param>
 /// <param name="tokenBytes">The number of bytes to send.</param>
 /// <param name="type">The type of the USB Request.</param>
 /// <param name="req">The specific USB Request.</param>
 /// <param name="hiVal">The USB Request Hi-Val.</param>
 /// <param name="loVal">The USB Request Lo-Val.</param>
 /// <param name="index">The USB request index.</param>
 /// <param name="length">The length of the USB request.</param>
 protected abstract void _SETUPTransaction(USBTransfer transfer, USBTransaction uTransaction, bool toggle, ushort tokenBytes,
                                           byte type, byte req, byte hiVal, byte loVal, ushort index, ushort length);
Example #12
0
 /// <summary>
 /// When overridden in a derived class, handles HC implementation specific OUT transaction initialisation.
 /// </summary>
 /// <param name="transfer">The transfer to which the transaction should be added.</param>
 /// <param name="uTransaction">The USB Transaction to convert to an EHCI transaction.</param>
 /// <param name="toggle">The transaction toggle state.</param>
 /// <param name="buffer">The buffer of outgoing data.</param>
 /// <param name="length">The length of the buffer.</param>
 protected abstract void _OUTTransaction(USBTransfer transfer, USBTransaction uTransaction, bool toggle, void* buffer, ushort length);
Example #13
0
 /// <summary>
 /// When overridden in a derived class, handles HC implementation specific SETUP transaction initialisation.
 /// </summary>
 /// <param name="transfer">The transfer to which the transaction should be added.</param>
 /// <param name="uTransaction">The USB Transaction to convert to an EHCI Transaction.</param>
 /// <param name="toggle">The transaction toggle state.</param>
 /// <param name="tokenBytes">The number of bytes to send.</param>
 /// <param name="type">The type of the USB Request.</param>
 /// <param name="req">The specific USB Request.</param>
 /// <param name="hiVal">The USB Request Hi-Val.</param>
 /// <param name="loVal">The USB Request Lo-Val.</param>
 /// <param name="index">The USB request index.</param>
 /// <param name="length">The length of the USB request.</param>
 protected abstract void _SETUPTransaction(USBTransfer transfer, USBTransaction uTransaction, bool toggle, ushort tokenBytes,
                                    byte type, byte req, byte hiVal, byte loVal, ushort index, ushort length);
Example #14
0
        /// <summary>
        /// Sets up an OUT transaction and adds it to the specified transfer.
        /// </summary>
        /// <param name="transfer">The transfer to which the transaction should be added.</param>
        /// <param name="controlHandshake">Whether the transaction is part of a control handshake or not.</param>
        /// <param name="buffer">The buffer of outgoing data.</param>
        /// <param name="length">The length of the buffer.</param>
        public void OUTTransaction(USBTransfer transfer, bool controlHandshake, void* buffer, ushort length)
        {
            ushort clampedLength = FOS_System.Math.Min(transfer.packetSize, length);
            length -= clampedLength;
            ushort remainingTransactions = (ushort)(length / transfer.packetSize);
            if (length % transfer.packetSize != 0)
                remainingTransactions++;

            USBTransaction transaction = new USBTransaction();
            transaction.type = USBTransactionType.OUT;

            if (controlHandshake) // Handshake transaction of control transfers always have toggle set to 1
            {
                ((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle = true;
            }

            _OUTTransaction(transfer, transaction, ((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle, buffer, clampedLength);

            transfer.transactions.Add(transaction);

            ((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle = !((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle; // Switch toggle

            if (remainingTransactions > 0)
            {
                OUTTransaction(transfer, controlHandshake, ((byte*)buffer + clampedLength), length);
            }
        }
Example #15
0
        /// <summary>
        /// Sets up an IN transaction and adds it to the specified transfer.
        /// </summary>
        /// <param name="transfer">The transfer to which the transaction should be added.</param>
        /// <param name="uTransaction">The USB Transaction to convert to an EHCI transaction.</param>
        /// <param name="toggle">The transaction toggle state.</param>
        /// <param name="buffer">The buffer to store the incoming data in.</param>
        /// <param name="length">The length of the buffer.</param>
        protected override void _INTransaction(USBTransfer transfer, USBTransaction uTransaction, bool toggle, void* buffer, ushort length)
        {
            // Create an EHCI-specific object to describe the transaction
            EHCITransaction eTransaction = new EHCITransaction();
            // Store the underlying HC-specific transaction info
            uTransaction.underlyingTz = eTransaction;
            // IN transaction so use the supplied input data buffer
            eTransaction.inBuffer = buffer;
            eTransaction.inLength = length;

#if EHCI_TRACE
            DBGMSG(((FOS_System.String)"IN Transaction : buffer=") + (uint)buffer);

            DBGMSG(((FOS_System.String)"IN Transaction : Before CreateQTD : bufferPtr=&qTDBuffer=") + (uint)buffer);
#endif

            // Create and initialise the IN queue transfer descriptor
            eTransaction.qTD = CreateQTD_IO(null, 1, toggle, length, length);

#if EHCI_TRACE
            DBGMSG(((FOS_System.String)"IN Transaction : After CreateQTD : bufferPtr=&qTDBuffer=") + (uint)buffer + ", Buffer0=" + (uint)eTransaction.qTD.Buffer0);
#endif
            // If the number of existing transactions is greater than 0
            //  i.e. some transactions have already been added. 
            if (transfer.transactions.Count > 0)
            {
                // Get the previous (i.e. last) transaction then the underlying transaction from it
                EHCITransaction eLastTransaction = (EHCITransaction)((USBTransaction)(transfer.transactions[transfer.transactions.Count - 1])).underlyingTz;
                // Create a wrapper for the last transaction (qTD)
                EHCI_qTD lastQTD = eLastTransaction.qTD;
                // Set the Next Transaction (qTD) Pointer on the previous qTD to point to the qTD
                //  we just created. 
                // Note: The NextqTDPointer must be the physical address of qTD data.
                lastQTD.NextqTDPointer = (EHCI_qTD_Struct*)VirtMemManager.GetPhysicalAddress(eTransaction.qTD.qtd);
                // Mark the previous qTD's Next Transaction Pointer as valid.
                lastQTD.NextqTDPointerTerminate = false;
            }
        }
Example #16
0
 /// <summary>
 /// When overridden in a derived class, handles HC implementation specific OUT transaction initialisation.
 /// </summary>
 /// <param name="transfer">The transfer to which the transaction should be added.</param>
 /// <param name="uTransaction">The USB Transaction to convert to an EHCI transaction.</param>
 /// <param name="toggle">The transaction toggle state.</param>
 /// <param name="buffer">The buffer of outgoing data.</param>
 /// <param name="length">The length of the buffer.</param>
 protected abstract void _OUTTransaction(USBTransfer transfer, USBTransaction uTransaction, bool toggle, void *buffer, ushort length);
Example #17
0
        /// <summary>
        /// Sets up an IN transaction and adds it to the specified transfer.
        /// </summary>
        /// <param name="transfer">The transfer to which the transaction should be added.</param>
        /// <param name="uTransaction">The USB Transaction to convert to an EHCI transaction.</param>
        /// <param name="toggle">The transaction toggle state.</param>
        /// <param name="buffer">The buffer of outgoing data.</param>
        /// <param name="length">The length of the buffer.</param>
        protected override void _OUTTransaction(USBTransfer transfer, USBTransaction uTransaction, bool toggle, void* buffer, ushort length)
        {
            // Create an EHCI-specific object to describe the transaction
            EHCITransaction eTransaction = new EHCITransaction();
            // Store the underlying HC-specific transaction info
            uTransaction.underlyingTz = eTransaction;
            // OUT transaction so there is no input buffer
            eTransaction.inBuffer = null;
            eTransaction.inLength = 0u;

            // Create and initialise the OUT queue transfer descriptor
            EHCI_qTD theQTD = CreateQTD_IO(null, 0, toggle, length, length);
            // Set the qTD structure in the transaction description object
            eTransaction.qTD = theQTD;
            // If there is an output buffer and it has > 0 length:
            if (buffer != null && length != 0)
            {
                // Copy the data from the output buffer to the transaction's output buffer
                // The transaction's output buffer has been allocated so it as aligned correctly
                //  where as there is no guarantee the output buffer passed to us has been so we
                //  must copy the data across.
                Utilities.MemoryUtils.MemCpy_32(theQTD.Buffer0VirtAddr, (byte*)buffer, length);

#if EHCI_TRACE
                BasicConsole.WriteLine("EHCI: OUTTransaction - Buffer0:");
                BasicConsole.DumpMemory(theQTD.Buffer0VirtAddr, length);
#endif
            }

            // If the number of existing transactions is greater than 0
            //  i.e. some transactions have already been added. 
            if (transfer.transactions.Count > 0)
            {
                // Get the previous (i.e. last) transaction then the underlying transaction from it
                EHCITransaction eLastTransaction = (EHCITransaction)((USBTransaction)(transfer.transactions[transfer.transactions.Count - 1])).underlyingTz;
                // Create a wrapper for the last transaction (qTD)
                EHCI_qTD lastQTD = eLastTransaction.qTD;
                // Set the Next Transaction (qTD) Pointer on the previous qTD to point to the qTD
                //  we just created. 
                // Note: The NextqTDPointer must be the physical address of qTD data.
                lastQTD.NextqTDPointer = (EHCI_qTD_Struct*)VirtMemManager.GetPhysicalAddress(eTransaction.qTD.qtd);
                // Mark the previous qTD's Next Transaction Pointer as valid.
                lastQTD.NextqTDPointerTerminate = false;
            }
        }
Example #18
0
        /// <summary>
        /// Sets up a SETUP transaction and adds it to the specified transfer.
        /// </summary>
        /// <param name="transfer">The transfer to which the transaction should be added.</param>
        /// <param name="tokenBytes">The number of bytes to send.</param>
        /// <param name="type">The type of the USB Request.</param>
        /// <param name="req">The specific USB Request.</param>
        /// <param name="hiVal">The USB Request Hi-Val.</param>
        /// <param name="loVal">The USB Request Lo-Val.</param>
        /// <param name="index">The USB request index.</param>
        /// <param name="length">The length of the USB request.</param>
        public void SETUPTransaction(USBTransfer transfer, ushort tokenBytes, byte type, byte req, byte hiVal, byte loVal, 
                                     ushort index, ushort length)
        {
            USBTransaction transaction = new USBTransaction();
            transaction.type = USBTransactionType.SETUP;

            _SETUPTransaction(transfer, transaction, false, tokenBytes, type, req, hiVal, loVal, index, length);

            transfer.transactions.Add(transaction);

            ((Endpoint)transfer.device.Endpoints[transfer.endpoint]).Toggle = true;
        }