private static void InitTransmit(EHCITransferDescriptor *td, EHCITransferDescriptor *previous, USBDeviceSpeed speed, uint address, uint endp, uint toggle, uint type, uint len, byte *data) { td->NextLink = TD_TERMINATE; td->Reserved = TD_TERMINATE; td->Next = null; // Add link if (previous != null) { previous->NextLink = (int)td; previous->Next = td; } // Set token td->Token = (int)((toggle << TD_TOK_TOGGLE_SHIFT) | (len << TD_TOK_TBTT_SHIFT) | (3 << TD_TOK_CERR_SHIFT) | (type << TD_TOK_PID_SHIFT) | TD_TOK_STATUS_ACTIVE); // Set data buffer int ptr = (int)data; td->Buffer[0] = ptr; td->ExtBuffer[0] = (ptr >> 32); ptr &= ~0xFFF; for (int i = 1; i < 4; i++) { ptr += 0x1000; td->Buffer[i] = ptr; td->ExtBuffer[i] = (ptr >> 32); } }
/// <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; } } }
public static void FreeTransmit(EHCIController controller, EHCITransferDescriptor *transmit) { transmit->Allocated = false; }
private unsafe static EHCITransferDescriptor *AllocateEmptyTransmit(EHCIController controller) { EHCITransferDescriptor *queueHead = GetTransmitDescriptor(controller); return(queueHead); }
/// <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); }