diff --git a/src/usb-device-control.adb b/src/usb-device-control.adb index 96fde63..a088907 100644 --- a/src/usb-device-control.adb +++ b/src/usb-device-control.adb @@ -116,7 +116,7 @@ package body USB.Device.Control is -- Exception: handle set address request here if This.Ctrl.Req.RType = (Dev, 0, Stand, Host_To_Device) and then - This.Ctrl.Req.Request = 5 -- SET_ADDRESS + This.Ctrl.Req.Request = Req_Set_Address'Enum_Rep then This.UDC.Set_Address (UInt7 (This.Ctrl.Req.Value and 16#7F#)); @@ -252,21 +252,21 @@ package body USB.Device.Control is end if; case Req.Request is - when 0 => -- GET_STATUS + when Req_Get_Status'Enum_Rep => return Get_Status (This, Req); - when 1 => -- CLEAR_FEATURE + when Req_Clear_Feature'Enum_Rep => raise Program_Error with "CLEAR_FEATURE not implemented"; - when 3 => -- SET_FEATURE + when Req_Set_Feature'Enum_Rep => raise Program_Error with "SET_FEATURE not implemented"; - when 5 => -- SET_ADDRESS + when Req_Set_Address'Enum_Rep => return Set_Address (This, Req); - when 6 => -- GET_DESCRIPTOR + when Req_Get_Descriptor'Enum_Rep => return Get_Descriptor (This, Req); - when 7 => -- SET_DESCRIPTOR + when Req_Set_Descriptor'Enum_Rep => raise Program_Error with "SET_DESCRIPTOR not implemented"; - when 8 => -- GET_CONFIGURATION + when Req_Get_Configuration'Enum_Rep => raise Program_Error with "GET_CONFIGURATION not implemented"; - when 9 => -- SET_CONFIGURATION + when Req_Set_Configuration'Enum_Rep => return Set_Configuration (This, Req); when others => return Not_Supported; @@ -289,10 +289,10 @@ package body USB.Device.Control is EP : constant EP_Addr := (Id, Dir); begin case Req.Request is - when 0 => -- GET_STATUS + when Req_Get_Status'Enum_Rep => raise Program_Error with "EP GET_STATUS not implemented"; - when 1 => -- CLEAR_FEATURE + when Req_Clear_Feature'Enum_Rep => case Req.Value is when 0 => -- HALT ENDPOINT This.UDC.EP_Stall (EP, False); @@ -301,7 +301,7 @@ package body USB.Device.Control is raise Program_Error with "Invalid EP CLEAR_FEATURE"; end case; - when 3 => -- SET_FEATURE + when Req_Set_Feature'Enum_Rep => case Req.Value is when 0 => -- HALT ENDPOINT This.UDC.EP_Stall (EP, True); @@ -310,7 +310,7 @@ package body USB.Device.Control is raise Program_Error with "Invalid EP SET_FEATURE"; end case; - when 16#12# => -- SYNCH_FRAME + when Req_Sync_Feature'Enum_Rep => raise Program_Error with "EP SYNCH_FEATURE not implemented"; when others => diff --git a/src/usb-device-hid.adb b/src/usb-device-hid.adb index f684bab..801fa02 100644 --- a/src/usb-device-hid.adb +++ b/src/usb-device-hid.adb @@ -37,6 +37,15 @@ package body USB.Device.HID is subtype Dispatch is Abstract_HID_Class'Class; + type Class_Request_Type is + (Get_Report, Get_Idle, Get_Protocol, Set_Report, Set_Idle, Set_Protocol); + for Class_Request_Type use (Get_Report => 1, + Get_Idle => 2, + Get_Protocol => 3, + Set_Report => 9, + Set_Idle => 10, + Set_Protocol => 11); + ---------------- -- Initialize -- ---------------- @@ -89,17 +98,16 @@ package body USB.Device.HID is is F : constant Natural := Data'First; - USB_DESC_TYPE_INTERFACE : constant := 4; - USB_DESC_TYPE_ENDPOINT : constant := 5; + USB_CLASS_HID : constant := 3; begin Data (F + 0 .. F + 24) := (9, - USB_DESC_TYPE_INTERFACE, + Dt_Interface'Enum_Rep, 0, -- This.Interface_Index, 0, -- Alternate setting 1, -- Number of endpoints - 3, -- Class HID + USB_CLASS_HID, -- Class HID 0, -- Subclass 0, -- Interface protocol 0=none, 1=keyboard, 2=mouse 0, -- Str @@ -114,9 +122,9 @@ package body USB.Device.HID is Dispatch (This).Report_Descriptor'Length, 0, -- Descriptor length 7, - USB_DESC_TYPE_ENDPOINT, + Dt_Endpoint'Enum_Rep, 16#80# or UInt8 (This.EP), -- In EP - 3, -- Interrupt EP + Interrupt'Enum_Rep, -- Interrupt EP 16#40#, 0, -- TODO: Max packet size 1 -- Polling interval ); @@ -162,11 +170,11 @@ package body USB.Device.HID is if Req.RType.Typ = Class and then Req.RType.Recipient = Iface then case Req.Request is - when 1 => -- GET_REPORT + when Get_Report'Enum_Rep => return Not_Supported; - when 2 => -- GET_IDLE + when Get_Idle'Enum_Rep => return Not_Supported; - when 3 => -- GET_PROTOCOL + when Get_Protocol'Enum_Rep => return Not_Supported; when others => raise Program_Error with "Unknown HID request"; @@ -175,7 +183,7 @@ package body USB.Device.HID is if Req.RType.Typ = Stand and then - Req.Request = 6 -- GET_DESCRIPTOR + Req.Request = Req_Get_Descriptor'Enum_Rep then declare -- Index : constant UInt8 := UInt8 (Req.Value and 16#FF#); @@ -217,17 +225,17 @@ package body USB.Device.HID is begin if Req.RType.Typ = Class and then Req.RType.Recipient = Iface then case Req.Request is - when 9 => -- SET_REPORT + when Set_Report'Enum_Rep => declare Typ : constant UInt8 := Utils.High (Req.Value); ID : constant UInt8 := Utils.Low (Req.Value); begin return Dispatch (This).Set_Report (Typ, ID, Data); end; - when 10 => -- SET_IDLE + when Set_Idle'Enum_Rep => This.Idle_State := Utils.High (Req.Value); return Handled; - when 11 => -- SET_PROTOCOL + when Set_Protocol'Enum_Rep => return Not_Supported; when others => raise Program_Error with "Unknown HID request"; diff --git a/src/usb-device-midi.adb b/src/usb-device-midi.adb index 6021f32..b7838cb 100644 --- a/src/usb-device-midi.adb +++ b/src/usb-device-midi.adb @@ -41,6 +41,15 @@ package body USB.Device.MIDI is EP_Buffer_Size : constant := 64; + type Class_Request_Type is + (Get_Report, Get_Idle, Get_Protocol, Set_Report, Set_Idle, Set_Protocol); + for Class_Request_Type use (Get_Report => 1, + Get_Idle => 2, + Get_Protocol => 3, + Set_Report => 9, + Set_Idle => 10, + Set_Protocol => 11); + ------------- -- Receive -- ------------- @@ -231,9 +240,8 @@ package body USB.Device.MIDI is Data : out UInt8_Array) is F : constant Natural := Data'First; - USB_DESC_TYPE_INTERFACE : constant := 4; - USB_DESC_TYPE_ENDPOINT : constant := 5; + USB_CLASS_AUDIO : constant := 1; begin pragma Style_Checks (Off); @@ -245,11 +253,11 @@ package body USB.Device.MIDI is -- descriptor follows inline: Data (F + 0 .. F + 91) := (9, -- sizeof(usbDescrInterface): length of descriptor in bytes - USB_DESC_TYPE_INTERFACE, -- descriptor type + Dt_Interface'Enum_Rep, -- descriptor type UInt8 (This.Interface_Index), -- index of this interface 0, -- alternate setting for this interface 0, -- endpoints excl 0: number of endpoint descriptors to follow - 1, -- Class audio + USB_CLASS_AUDIO, -- Class audio 1, -- Subclass control 0, -- UInt8 (This.Iface_Str), -- string index for interface @@ -275,11 +283,11 @@ package body USB.Device.MIDI is -- B.4.1 Standard MS Interface Descriptor -- descriptor follows inline: 9, -- length of descriptor in bytes - USB_DESC_TYPE_INTERFACE, -- descriptor type + Dt_Interface'Enum_Rep, -- descriptor type UInt8 (This.Interface_Index + 1), -- index of this interface 0, -- alternate setting for this interface 2, -- endpoints excl 0: number of endpoint descriptors to follow - 1, -- AUDIO + USB_CLASS_AUDIO, -- AUDIO 3, -- MIDI Streaming 0, -- unused UInt8 (This.Iface_Str), -- string index for interface @@ -339,9 +347,9 @@ package body USB.Device.MIDI is -- B.5.1 Standard Bulk OUT Endpoint Descriptor -- descriptor follows inline: 9, -- bLenght - USB_DESC_TYPE_ENDPOINT, -- bDescriptorType = endpoint + Dt_Endpoint'Enum_Rep, -- bDescriptorType = endpoint UInt8 (This.EP), -- bEndpointAddress OUT endpoint number 1 - 2, -- bmAttributes: 2:Bulk, 3:Interrupt endpoint + Bulk'Enum_Rep, -- bmAttributes: 2:Bulk, 3:Interrupt endpoint EP_Buffer_Size, 0, -- wMaxPacketSize 10, -- bInterval in ms 0, -- bRefresh @@ -360,9 +368,9 @@ package body USB.Device.MIDI is -- B.6.1 Standard Bulk IN Endpoint Descriptor -- descriptor follows inline: 9, -- bLenght - USB_DESC_TYPE_ENDPOINT, -- bDescriptorType = endpoint + Dt_Endpoint'Enum_Rep, -- bDescriptorType = endpoint 16#80# or UInt8 (This.EP), -- bEndpointAddress IN endpoint number 1 - 2, -- bmAttributes: 2: Bulk, 3: Interrupt endpoint + Bulk'Enum_Rep, -- Bulk EP EP_Buffer_Size, 0, -- wMaxPacketSize 10, -- bInterval in ms 0, -- bRefresh @@ -427,18 +435,18 @@ package body USB.Device.MIDI is if Req.RType.Typ = Class and then Req.RType.Recipient = Iface then case Req.Request is - when 1 => -- GET_REPORT + when Get_Report'Enum_Rep => return Not_Supported; - when 2 => -- GET_IDLE + when Get_Idle'Enum_Rep => return Not_Supported; - when 3 => -- GET_PROTOCOL + when Get_Protocol'Enum_Rep => return Not_Supported; - when 9 => -- SET_REPORT + when Set_Report'Enum_Rep => return Not_Supported; - when 10 => -- SET_IDLE - This.Idle_State := UInt8 (Shift_Right (Req.Value, 8) and 16#FF#); + when Set_Idle'Enum_Rep => + This.Idle_State := Utils.High (Req.Value); return Handled; - when 11 => -- SET_PROTOCOL + when Set_Protocol'Enum_Rep => return Not_Supported; when others => return Next_Callback; @@ -447,12 +455,11 @@ package body USB.Device.MIDI is if Req.RType.Typ = Stand and then - Req.Request = 6 -- GET_DESCRIPTOR + Req.Request = Req_Get_Descriptor'Enum_Rep then declare - -- Index : constant UInt8 := UInt8 (Req.Value and 16#FF#); - Desc_Type : constant UInt8 := - UInt8 (Shift_Right (Req.Value, 8) and 16#FF#); + -- Index : constant UInt8 := Utils.Low (Req.Value); + Desc_Type : constant UInt8 := Utils.High (Req.Value); begin case Desc_Type is diff --git a/src/usb-device-serial.adb b/src/usb-device-serial.adb index 8d962cb..a138082 100644 --- a/src/usb-device-serial.adb +++ b/src/usb-device-serial.adb @@ -43,6 +43,13 @@ package body USB.Device.Serial is Irq_Buffer_Size : constant := 64; Bulk_Buffer_Size : constant := 64; -- Linux only supports up to 64 bytes + type Class_Request_Type is + (Set_Line_Coding, Get_Line_Coding, Set_Control_Line_State, Send_Break); + for Class_Request_Type use (Set_Line_Coding => 16#20#, + Get_Line_Coding => 16#21#, + Set_Control_Line_State => 16#22#, + Send_Break => 16#23#); + ---------------- -- Initialize -- ---------------- @@ -126,9 +133,6 @@ package body USB.Device.Serial is is F : constant Natural := Data'First; - USB_DESC_TYPE_INTERFACE : constant := 4; - USB_DESC_TYPE_ENDPOINT : constant := 5; - USB_DESC_CS_INTERFACE : constant := 16#24#; USB_CLASS_CDC : constant := 2; USB_CLASS_CDC_DATA : constant := 10; CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL : constant := 2; @@ -141,7 +145,7 @@ package body USB.Device.Serial is ( -- Interface Associate -- 8, -- bLength - 16#0B#, -- bDescriptorType 0x0B + Dt_Interface_Associate'Enum_Rep, -- bDescriptorType UInt8 (This.Interface_Index), -- bFirstInterface 2, -- bInterfaceCount USB_CLASS_CDC, -- bFunctionClass @@ -151,7 +155,7 @@ package body USB.Device.Serial is -- CDC Control Interface -- 9, -- bLength - USB_DESC_TYPE_INTERFACE, -- bDescriptorType + Dt_Interface'Enum_Rep, -- bDescriptorType UInt8 (This.Interface_Index), -- bInterfaceNumber 0, -- bAlternateSetting 1, -- bNumEndpoints @@ -162,42 +166,42 @@ package body USB.Device.Serial is -- CDC Header -- 5, - USB_DESC_CS_INTERFACE, + Dt_Cs_Interface'Enum_Rep, CDC_FUNC_DESC_HEADER, 16#20#, 16#01#, -- CDC Call -- 5, - USB_DESC_CS_INTERFACE, + Dt_Cs_Interface'Enum_Rep, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, UInt8 (This.Interface_Index + 1), -- CDC ACM: support line request -- 4, - USB_DESC_CS_INTERFACE, + Dt_Cs_Interface'Enum_Rep, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2, -- CDC Union -- 5, - USB_DESC_CS_INTERFACE, + Dt_Cs_Interface'Enum_Rep, CDC_FUNC_DESC_UNION, UInt8 (This.Interface_Index), UInt8 (This.Interface_Index + 1), -- Endpoint Notification -- 7, - USB_DESC_TYPE_ENDPOINT, + Dt_Endpoint'Enum_Rep, 16#80# or UInt8 (This.Int_EP), -- In EP - 3, -- Interrupt EP + Interrupt'Enum_Rep, -- Interrupt EP Irq_Buffer_Size, 0, 16, -- Polling interval -- CDC Control Interface -- 9, -- bLength - USB_DESC_TYPE_INTERFACE, -- bDescriptorType + Dt_Interface'Enum_Rep, -- bDescriptorType UInt8 (This.Interface_Index + 1), -- bInterfaceNumber 0, -- bAlternateSetting 2, -- bNumEndpoints @@ -208,17 +212,17 @@ package body USB.Device.Serial is -- Endpoint Data out -- 7, - USB_DESC_TYPE_ENDPOINT, + Dt_Endpoint'Enum_Rep, UInt8 (This.Bulk_EP), -- Out EP - 2, -- Bulk EP + Bulk'Enum_Rep, -- Bulk EP Bulk_Buffer_Size, 0, 0, -- Polling interval -- Endpoint Data in -- 7, - USB_DESC_TYPE_ENDPOINT, + Dt_Endpoint'Enum_Rep, 16#80# or UInt8 (This.Bulk_EP), -- In EP - 2, -- Bulk EP + Bulk'Enum_Rep, -- Bulk EP Bulk_Buffer_Size, 0, 0 @@ -273,7 +277,7 @@ package body USB.Device.Serial is if Req.RType.Typ = Class and then Req.RType.Recipient = Iface then case Req.Request is - when 16#21# => -- GET_LINE_CODING + when Get_Line_Coding'Enum_Rep => Buf := This.Coding'Address; Len := This.Coding'Size / 8; return Handled; @@ -298,7 +302,7 @@ package body USB.Device.Serial is begin if Req.RType.Typ = Class and then Req.RType.Recipient = Iface then case Req.Request is - when 16#20# => -- SET_LINE_CODING + when Set_Line_Coding'Enum_Rep => if Data'Length = (This.Coding'Size / 8) then declare Dst : UInt8_Array (1 .. This.Coding'Size / 8) @@ -310,11 +314,11 @@ package body USB.Device.Serial is else return Not_Supported; end if; - when 16#22# => -- SET_CONTROL_LINE_STATE + when Set_Control_Line_State'Enum_Rep => This.State.DTE_Is_Present := (Req.Value and 1) /= 0; This.State.Half_Duplex_Carrier_control := (Req.Value and 2) /= 0; return Handled; - when 16#23# => -- SEND_BREAK + when Send_Break'Enum_Rep => -- TODO: Break are ignored for now... return Handled; when others => diff --git a/src/usb-device.adb b/src/usb-device.adb index 3a8b0e7..4fe2455 100644 --- a/src/usb-device.adb +++ b/src/usb-device.adb @@ -36,6 +36,8 @@ with USB.Device.Control; with USB.Logging.Device; +with USB.Utils; + package body USB.Device is procedure Put_Line (Str : String); @@ -94,7 +96,7 @@ package body USB.Device is if Index = 0 then This.Ctrl.Buffer (1) := 4; -- bLength - This.Ctrl.Buffer (2) := 3; -- bDescriptorType (String) + This.Ctrl.Buffer (2) := Dt_String'Enum_Rep; -- 0x03 -- LANG_EN_US This.Ctrl.Buffer (3) := ASCII.HT'Enum_Rep; -- 0x04 @@ -115,7 +117,7 @@ package body USB.Device is with Address => This.Ctrl.Buffer (3)'Address; begin This.Ctrl.Buffer (1) := UInt8 (Len + 2); -- bLength - This.Ctrl.Buffer (2) := 3; -- bDescriptorType (String) + This.Ctrl.Buffer (2) := Dt_String'Enum_Rep; Dst := This.String_Buffer (Info.From .. Info.To); end; @@ -132,28 +134,26 @@ package body USB.Device is Req : Setup_Data) return Setup_Request_Answer is - Index : constant UInt8 := UInt8 (Req.Value and 16#FF#); - Desc_Type : constant UInt8 := - UInt8 (Shift_Right (Req.Value, 8) and 16#FF#); + Index : constant UInt8 := Utils.Low (Req.Value); + Desc_Type : constant UInt8 := Utils.High (Req.Value); begin case Desc_Type is - when 1 => -- DT_DEVICE + when Dt_Device'Enum_Rep => Put_Line ("DT_DEVICE"); This.Build_Device_Descriptor; return Handled; - when 2 => -- DT_CONFIGURATION + when Dt_Configuration'Enum_Rep => Put_Line ("DT_CONFIGURATION"); This.Build_Config_Descriptor; return Handled; - when 3 => -- DT_STRING + when Dt_String'Enum_Rep => Put_Line ("DT_STRING"); return Get_String (This, String_Id (Index)); - when 6 => -- DT_QUALIFIER - + when Dt_Qualifier'Enum_Rep => Put_Line ("DT_QUALIFIER"); This.Build_Device_Qualifier; return Handled; @@ -476,7 +476,7 @@ package body USB.Device is with Address => This.Ctrl.Buffer'Address; begin Desc := (bLength => Desc'Size / 8, - bDescriptorType => 1, -- DT_DEVICE + bDescriptorType => Dt_Device'Enum_Rep, bcdUSB => 16#0110#, bDeviceClass => 0, bDeviceSubClass => 0, @@ -505,7 +505,7 @@ package body USB.Device is with Address => This.Ctrl.Buffer'Address; begin Desc := (bLength => Desc'Size / 8, - bDescriptorType => 6, -- DT_QUALIFIER + bDescriptorType => Dt_Qualifier'Enum_Rep, bcdUSB => 16#0200#, bDeviceClass => 0, bDeviceSubClass => 0, diff --git a/src/usb.ads b/src/usb.ads index f2e69e9..67a2496 100644 --- a/src/usb.ads +++ b/src/usb.ads @@ -82,6 +82,20 @@ package USB is Dir : Data_Phase_Transfer_Direction; end record with Pack, Size => 8; + type Stand_Request_Type is + (Req_Get_Status, Req_Clear_Feature, Req_Set_Feature, Req_Set_Address, + Req_Get_Descriptor, Req_Set_Descriptor, Req_Get_Configuration, + Req_Set_Configuration, Req_Sync_Feature); + for Stand_Request_Type use (Req_Get_Status => 16#00#, + Req_Clear_Feature => 16#01#, + Req_Set_Feature => 16#03#, + Req_Set_Address => 16#05#, + Req_Get_Descriptor => 16#06#, + Req_Set_Descriptor => 16#07#, + Req_Get_Configuration => 16#08#, + Req_Set_Configuration => 16#09#, + Req_Sync_Feature => 16#12#); + type Setup_Data is record RType : Request_Type; Request : UInt8; @@ -107,6 +121,18 @@ package USB is type Lang_ID is new UInt16; type Interface_Id is new UInt8; + type Descriptor_Type is + (Dt_Device, Dt_Configuration, Dt_String, Dt_Interface, Dt_Endpoint, + Dt_Qualifier, Dt_Interface_Associate, Dt_Cs_Interface); + for Descriptor_Type use (Dt_Device => 16#01#, + Dt_Configuration => 16#02#, + Dt_String => 16#03#, + Dt_Interface => 16#04#, + Dt_Endpoint => 16#05#, + Dt_Qualifier => 16#06#, + Dt_Interface_Associate => 16#0B#, + Dt_Cs_Interface => 16#24#); + type Device_Descriptor is record bLength : UInt8; bDescriptorType : UInt8;