private static void InitTransmit(UHCITransmitDescriptor *td, UHCITransmitDescriptor *previous, USBDeviceSpeed speed, uint address, uint endp, uint toogle, uint type, uint len, byte *data) { len = (len - 1) & 0x7FFF; if (previous != null) { previous->Link = (int)Paging.GetPhysicalFromVirtual(td) | TD_POINTER_DEPTH; previous->Next = td; } td->Link = TD_POINTER_TERMINATE; td->Next = null; td->Control = (int)((3 << (int)TD_ERROR_SHIFT) | TD_CONTROL_ACTIVE); if (speed == USBDeviceSpeed.LOW_SPEED) { td->Control |= (int)TD_CONTROL_LOW_SPEED; } td->Token = (len << TD_TOKEN_MAXLEN) | (toogle << TD_TOKEN_D_SHIFT) | (endp << TD_TOKEN_ENDP) | (address << TD_TOKEN_ADDR) | type; td->BufferPointer = (int)Paging.GetPhysicalFromVirtual(data); }
/// <summary> /// Prepare interrupt /// </summary> /// <param name="dev"></param> /// <param name="transfer"></param> private static void PrepareInterrupt(USBDevice dev, USBTransfer *transfer) { UHCIController controller = (UHCIController)dev.Controller; uint endp = (uint)(dev.EndPointDesc->Address & 0xF); UHCITransmitDescriptor *td = GetTransmit(controller); if (td == null) { transfer->Success = false; transfer->Executed = true; } UHCITransmitDescriptor *head = td; /** * Initalize read */ InitTransmit(td, null, dev.Speed, dev.Address, endp, dev.Toggle, TRANS_PACKET_IN, transfer->Length, transfer->Data); UHCIQueueHead *qh = GetQueueHead(controller); qh->Element = (int)Paging.GetPhysicalFromVirtual(head); qh->Head = 0; qh->Transfer = transfer; qh->Transmit = head; InsertHead(controller, qh); }
public static void RemoveTransmit(UHCIController controller, UHCITransmitDescriptor *transmit) { if (transmit->Previous != null) { if (transmit->Next != null) { transmit->Previous->Link = transmit->Next->Link; transmit->Previous->Next = transmit->Next; } else { transmit->Previous->Link = 0; transmit->Previous->Next = null; } } FreeTransmit(controller, transmit); }
/// <summary> /// Insert head /// </summary> /// <param name="controller">UHCIController</param> /// <param name="head"></param> public static void InsertTransmit(UHCIController controller, UHCITransmitDescriptor *transmit) { UHCITransmitDescriptor *end = transmit; while (true) { if (end->Next != null) { end = end->Next; } else { break; } } end->Next = transmit; end->Link = (int)transmit | 1; transmit->Link = 0; }
/// <summary> /// Transfer /// </summary> /// <param name="dev">Device</param> /// <param name="transfer">Transfers</param> /// <param name="length">Number of transfers</param> private static unsafe void TransferOne(USBDevice dev, USBTransfer *transfer) { USBDeviceRequest request = transfer->Request; UHCIController controller = (UHCIController)dev.Controller; UHCITransmitDescriptor *td = GetTransmit(controller); InitTransmit(td, null, dev.Speed, dev.Address, transfer->Endpoint, dev.Toggle, (transfer->Type == 0) ? TRANS_PACKET_IN : TRANS_PACKET_OUT, transfer->Length, transfer->Data); UHCIQueueHead *qh = GetQueueHead(controller); qh->Element = (int)Paging.GetPhysicalFromVirtual(td); qh->Head = 0; qh->Transfer = transfer; qh->Transmit = td; InsertHead(controller, qh); WaitForQueueHead(controller, qh); }
public static void FreeTransmit(UHCIController controller, UHCITransmitDescriptor *transmit) { transmit->Allocated = false; }
/// <summary> /// Process Queue Head /// </summary> /// <param name="device"></param> /// <param name="head"></param> public static void ProcessHead(UHCIController controller, UHCIQueueHead *head) { USBTransfer *transfer = head->Transfer; UHCITransmitDescriptor *td = head->Transmit; if ((head->Element & ~0xF) == 0) { transfer->Executed = true; transfer->Success = true; } else { if ((td->Control & TD_CONTROL_NAK) > 0) { } if ((td->Control & TD_CONTROL_STALLED) > 0) { Console.WriteLine("Stalled"); transfer->Executed = true; transfer->Success = false; } if ((td->Control & TD_CONTROL_BABBLE) > 0) { Console.WriteLine("Control Babble error"); } if ((td->Control & TD_CONTROL_CRC) > 0) { Console.WriteLine("CRC Timeout"); transfer->Executed = true; transfer->Success = false; } if ((td->Control & TD_CONTROL_BITSTUFF) > 0) { Console.WriteLine("Bitstuff error"); } } if (transfer->Executed) { //if(transfer->ID > 0) //{ // PrintQueue(transfer->ID, head); //} head->Transfer = null; /** * We need to toggle endpoint state here */ /** * Remove head from schedule */ RemoveHead(controller, head); /** * Free transmit descriptors */ UHCITransmitDescriptor *tdE = td; while (tdE != null) { UHCITransmitDescriptor *next = tdE->Next; FreeTransmit(controller, tdE); tdE = next; } } }
/// <summary> /// Control USB Device /// </summary> /// <param name="dev"></param> /// <param name="transfer"></param> private static void Control(USBDevice dev, USBTransfer *transfer) { USBDeviceRequest request = transfer->Request; #if __UHCI_DIAG Console.WriteLine("------ UHCI Control message ---------"); Console.Write("Request: "); Console.WriteHex(request.Request); Console.WriteLine(""); Console.Write("Index: "); Console.WriteHex(request.Index); Console.WriteLine(""); Console.Write("Length:"); Console.WriteHex(request.Length); Console.WriteLine(""); Console.Write("Type:"); Console.WriteHex(request.Type); Console.WriteLine(""); Console.Write("Value:"); Console.WriteHex(request.Value); Console.WriteLine(""); Console.WriteLine("--------------------------------------"); #endif UHCIController controller = (UHCIController)dev.Controller; UHCITransmitDescriptor *td = GetTransmit(controller); UHCITransmitDescriptor *head = td; UHCITransmitDescriptor *prev = null; USBDeviceRequest *a = (USBDeviceRequest *)Heap.Alloc(sizeof(USBDeviceRequest)); a->Request = request.Request; a->Index = request.Index; a->Length = request.Length; a->Type = request.Type; a->Value = request.Value; InitTransmit(td, prev, dev.Speed, dev.Address, 0, 0, TRANS_PACKET_SETUP, (uint)sizeof(USBDeviceRequest), (byte *)a); prev = td; uint packetType = ((request.Type & USBDevice.TYPE_DEVICETOHOST) > 0) ? TRANS_PACKET_IN : TRANS_PACKET_OUT; byte *ptr = transfer->Data; uint packetSize = transfer->Length; uint offset = 0; uint toggle = 0; uint remaining = packetSize; while (remaining > 0) { td = GetTransmit(controller); if (td == null) { return; } packetSize = remaining; if (packetSize > dev.MaxPacketSize) { packetSize = dev.MaxPacketSize; } remaining -= packetSize; toggle ^= 1; InitTransmit(td, prev, dev.Speed, dev.Address, 0, toggle, packetType, packetSize, ptr + offset); prev = td; offset += packetSize; } td = GetTransmit(controller); if (td == null) { return; } packetType = ((request.Type & USBDevice.TYPE_DEVICETOHOST) > 0) ? TRANS_PACKET_OUT : TRANS_PACKET_IN; toggle = 1; InitTransmit(td, prev, dev.Speed, dev.Address, 0, toggle, packetType, 0, null); UHCIQueueHead *qh = GetQueueHead(controller); qh->Element = (int)Paging.GetPhysicalFromVirtual(head); qh->Head = 0; qh->Transfer = transfer; qh->Transmit = head; InsertHead(controller, qh); WaitForQueueHead(controller, qh); }