public static void RemoveHead(EHCIController controller, EHCIQueueHead *head) { mMutex.Lock(); /** * Set next to previous */ if (head->Previous != null) { if (head->Next != null) { head->Previous->Head = head->Head; head->Previous->Next = head->Next; } else { head->Previous->Head = TD_TERMINATE; head->Previous->Next = null; } } /** * Set previous to next */ if (head->Next != null) { head->Next->Previous = head->Previous; } head->Allocated = false; mMutex.Unlock(); }
public static void WaitForQueueHead(EHCIController controller, EHCIQueueHead *head) { while (!head->Transfer->Executed) { ProcessHead(controller, head); } }
/// <summary> /// Insert head /// </summary> /// <param name="controller">UHCIController</param> /// <param name="head"></param> public static void InsertHead(EHCIController controller, EHCIQueueHead *head) { mMutex.Lock(); EHCIQueueHead *end = controller.FirstHead; while (true) { if (end->Next != null) { end = end->Next; } else { break; } } head->Head = TD_TERMINATE; head->Previous = end; head->Next = null; end->Next = head; end->Head = (int)Paging.GetPhysicalFromVirtual(head); mMutex.Unlock(); }
private unsafe static EHCIQueueHead *AllocateEmptyQH(EHCIController controller) { EHCIQueueHead *queueHead = GetQueueHead(controller); queueHead->Head = FL_TERMINATE; queueHead->EPCapabilities = 0x00; queueHead->EPCharacteristics = 0x00; queueHead->CurLink = 0x00; queueHead->NextLink = 0x00; queueHead->Token = 0x00; queueHead->BufferPointer = 0x00; queueHead->Next = null; queueHead->Previous = null; queueHead->Transfer = null; return(queueHead); }
/// <summary> /// Process Queue Head /// </summary> /// <param name="device"></param> /// <param name="head"></param> public static void ProcessHead(EHCIController controller, EHCIQueueHead *head) { USBTransfer *transfer = head->Transfer; EHCITransferDescriptor *td = head->Transmit; Console.WriteHex(td->Token); Console.WriteLine(" :)"); 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 */ EHCITransferDescriptor *tdE = td; while (tdE != null) { EHCITransferDescriptor *next = tdE->Next; FreeTransmit(controller, tdE); tdE = next; } } }
private static void InitHead(EHCIQueueHead *qh, EHCIQueueHead *previous, uint addr, uint endp, uint maxSize) { qh->NextLink = TD_TERMINATE; qh->Reserved = TD_TERMINATE; qh->Next = null; // Add link if (previous != null) { previous->NextLink = (int)qh | 1; previous->Next = qh; } // Setup chars and caps qh->EPCharacteristics = (int)(QH_DTC | (0x3 << QH_EPS_SHIFT) | (endp << QH_ENDP_SHIFT) | (maxSize << QH_MAXLEN_SHIFT) | (addr << QH_EC_ADDR_SHIFT)); qh->EPCapabilities = (1 << 30); qh->Token = 0; }
/// <summary> /// Control USB Device /// </summary> /// <param name="dev"></param> /// <param name="transfer"></param> private unsafe static void Control(USBDevice dev, USBTransfer *transfer) { USBDeviceRequest request = transfer->Request; transfer->Executed = false; EHCIController controller = (EHCIController)dev.Controller; EHCITransferDescriptor *td = AllocateEmptyTransmit(controller); EHCITransferDescriptor *head = td; EHCITransferDescriptor *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 = AllocateEmptyTransmit(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 = AllocateEmptyTransmit(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); EHCIQueueHead *qh = AllocateEmptyQH(controller); InitHead(qh, null, dev.Address, 0, packetSize); qh->NextLink = (int)td; qh->Transmit = td; qh->Transfer = transfer; InsertHead(controller, qh); WaitForQueueHead(controller, qh); }