1 // 2 // Copyright (c) 2010-2018 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.Collections.Generic; 9 using System.Linq; 10 using Antmicro.Renode.Logging; 11 using Antmicro.Renode.Utilities; 12 13 namespace Antmicro.Renode.Core.USB.HID 14 { 15 public class Interface : USBInterface 16 { Interface(IUSBDevice device, byte identifier, byte subClassCode = (byte)SubclassCode.BootInterfaceSubclass, byte protocol = (byte)HID.Protocol.None, string description = null, ReportDescriptor reportDescriptor = null)17 public Interface(IUSBDevice device, 18 byte identifier, 19 byte subClassCode = (byte)SubclassCode.BootInterfaceSubclass, 20 byte protocol = (byte)HID.Protocol.None, 21 string description = null, 22 ReportDescriptor reportDescriptor = null) : base(device, identifier, USBClassCode.HumanInterfaceDevice, subClassCode, protocol, description) 23 { 24 HID_ReportDescriptor = reportDescriptor ?? new ReportDescriptor(); 25 HID_Descriptor = new HID.Descriptor(HID_ReportDescriptor); 26 27 RegisterSubdescriptor(HID_Descriptor, 0); 28 } 29 30 public HID.Descriptor HID_Descriptor { get; } 31 public ReportDescriptor HID_ReportDescriptor { get; } 32 HandleRequest(SetupPacket packet)33 public override BitStream HandleRequest(SetupPacket packet) 34 { 35 switch(packet.Type) 36 { 37 case PacketType.Standard: 38 return HandleStandardRequest(packet.Direction, (StandardRequest)packet.Request, packet.Value); 39 case PacketType.Class: 40 return HandleClassRequest(packet.Direction, (HidClassRequest)packet.Request, packet.Value); 41 default: 42 device.Log(LogLevel.Warning, "Unsupported type: 0x{0:X}", packet.Type); 43 return BitStream.Empty; 44 } 45 } 46 HandleClassRequest(Direction direction, HidClassRequest request, ushort value)47 private BitStream HandleClassRequest(Direction direction, HidClassRequest request, ushort value) 48 { 49 switch(request) 50 { 51 case HidClassRequest.SetIdle: 52 // we simply ignore this as we don't implement any repeated interrupts at all 53 return BitStream.Empty; 54 default: 55 device.Log(LogLevel.Warning, "Unsupported class request: 0x{0:X}", request); 56 return BitStream.Empty; 57 } 58 } 59 HandleStandardRequest(Direction direction, StandardRequest request, ushort value)60 private BitStream HandleStandardRequest(Direction direction, StandardRequest request, ushort value) 61 { 62 switch(request) 63 { 64 case StandardRequest.GetDescriptor: 65 if(direction != Direction.DeviceToHost) 66 { 67 device.Log(LogLevel.Warning, "Unexpected standard request direction"); 68 return BitStream.Empty; 69 } 70 return HandleGetDescriptor(value); 71 default: 72 device.Log(LogLevel.Warning, "Unsupported standard request: 0x{0:X}", request); 73 return BitStream.Empty; 74 } 75 } 76 HandleGetDescriptor(ushort value)77 private BitStream HandleGetDescriptor(ushort value) 78 { 79 var descriptorType = (DescriptorType)(value >> 8); 80 81 switch(descriptorType) 82 { 83 case DescriptorType.HID: 84 return HID_Descriptor.GetDescriptor(false); 85 case DescriptorType.Report: 86 return HID_ReportDescriptor.GetDescriptor(false); 87 default: 88 device.Log(LogLevel.Warning, "Unsupported descriptor type: 0x{0:X}", descriptorType); 89 return BitStream.Empty; 90 } 91 } 92 93 private enum HidClassRequest 94 { 95 GetReport = 0x1, 96 GetIdle = 0x2, 97 GetProtocol = 0x3, 98 // 0x4 - 0x8: reserved 99 SetReport = 0x9, 100 SetIdle = 0xa, 101 SetProtocol = 0xb 102 } 103 } 104 }