From f85a53a31b00190ad726f509ad275079fc6eb994 Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Wed, 15 Jul 2009 05:49:19 +0000 Subject: [PATCH] Fix HID class device driver -- if a SetIDle request is issued with the LSB of wValue set to zero, the idle period must be set for all HID interfaces. Fix Keyboard and Mouse demos, Idle period is now multiplied by 4 as the period is read into and sent out of the device to ensure it is always stored as a multiple of 1ms. Fixes Keyboard demo using an initial Idle period of 2s rather than 500ms (thanks to Brian Dickman). Move out the internal device serial descriptor reading routine into a seperate static function, rather than being part of USB_Device_GetDescriptor. --- Demos/Device/LowLevel/Keyboard/Keyboard.c | 12 +-- Demos/Device/LowLevel/Mouse/Mouse.c | 12 +-- LUFA/Drivers/USB/Class/Device/HID.c | 23 ++++-- LUFA/Drivers/USB/LowLevel/DevChapter9.c | 96 ++++++++++++----------- LUFA/Drivers/USB/LowLevel/DevChapter9.h | 4 + LUFA/ManPages/ChangeLog.txt | 1 + 6 files changed, 83 insertions(+), 65 deletions(-) diff --git a/Demos/Device/LowLevel/Keyboard/Keyboard.c b/Demos/Device/LowLevel/Keyboard/Keyboard.c index 185d968d74..2527148089 100644 --- a/Demos/Device/LowLevel/Keyboard/Keyboard.c +++ b/Demos/Device/LowLevel/Keyboard/Keyboard.c @@ -225,8 +225,8 @@ void EVENT_USB_UnhandledControlPacket(void) { Endpoint_ClearSETUP(); - /* Get idle period in MSB */ - IdleCount = (USB_ControlRequest.wValue >> 8); + /* Get idle period in MSB, IdleCount must be multiplied by 4 to get number of milliseconds */ + IdleCount = ((USB_ControlRequest.wValue & 0xFF00) >> 6); /* Acknowledge status stage */ while (!(Endpoint_IsINReady())); @@ -239,8 +239,8 @@ void EVENT_USB_UnhandledControlPacket(void) { Endpoint_ClearSETUP(); - /* Write the current idle duration to the host */ - Endpoint_Write_Byte(IdleCount); + /* Write the current idle duration to the host, must be divided by 4 before sent to host */ + Endpoint_Write_Byte(IdleCount >> 2); /* Send the flag to the host */ Endpoint_ClearIN(); @@ -329,8 +329,8 @@ void SendNextReport(void) /* Check if the idle period is set and has elapsed */ if ((IdleCount != HID_IDLE_CHANGESONLY) && (!(IdleMSRemaining))) { - /* Reset the idle time remaining counter, must multiply by 4 to get the duration in milliseconds */ - IdleMSRemaining = (IdleCount << 2); + /* Reset the idle time remaining counter */ + IdleMSRemaining = IdleCount; /* Idle period is set and has elapsed, must send a report to the host */ SendReport = true; diff --git a/Demos/Device/LowLevel/Mouse/Mouse.c b/Demos/Device/LowLevel/Mouse/Mouse.c index c0989c5db4..60eb7fad7b 100644 --- a/Demos/Device/LowLevel/Mouse/Mouse.c +++ b/Demos/Device/LowLevel/Mouse/Mouse.c @@ -197,8 +197,8 @@ void EVENT_USB_UnhandledControlPacket(void) { Endpoint_ClearSETUP(); - /* Get idle period in MSB */ - IdleCount = (USB_ControlRequest.wValue >> 8); + /* Get idle period in MSB, must multiply by 4 to get the duration in milliseconds */ + IdleCount = ((USB_ControlRequest.wValue & 0xFF00) >> 6); /* Acknowledge status stage */ while (!(Endpoint_IsINReady())); @@ -211,8 +211,8 @@ void EVENT_USB_UnhandledControlPacket(void) { Endpoint_ClearSETUP(); - /* Write the current idle duration to the host */ - Endpoint_Write_Byte(IdleCount); + /* Write the current idle duration to the host, must be divided by 4 before sent to host */ + Endpoint_Write_Byte(IdleCount >> 2); /* Send the flag to the host */ Endpoint_ClearIN(); @@ -289,8 +289,8 @@ void SendNextReport(void) /* Check if the idle period is set and has elapsed */ if ((IdleCount != HID_IDLE_CHANGESONLY) && (!(IdleMSRemaining))) { - /* Reset the idle time remaining counter, must multiply by 4 to get the duration in milliseconds */ - IdleMSRemaining = (IdleCount << 2); + /* Reset the idle time remaining counter */ + IdleMSRemaining = IdleCount; /* Idle period is set and has elapsed, must send a report to the host */ SendReport = true; diff --git a/LUFA/Drivers/USB/Class/Device/HID.c b/LUFA/Drivers/USB/Class/Device/HID.c index d0320868f8..bad934a3cd 100644 --- a/LUFA/Drivers/USB/Class/Device/HID.c +++ b/LUFA/Drivers/USB/Class/Device/HID.c @@ -38,8 +38,11 @@ void HID_Device_ProcessControlPacket(USB_ClassInfo_HID_Device_t* const HIDInterf if (!(Endpoint_IsSETUPReceived())) return; - if (USB_ControlRequest.wIndex != HIDInterfaceInfo->Config.InterfaceNumber) - return; + if ((USB_ControlRequest.wIndex != HIDInterfaceInfo->Config.InterfaceNumber) && + (USB_ControlRequest.bRequest != SetIdle)) + { + return; + } switch (USB_ControlRequest.bRequest) { @@ -105,12 +108,16 @@ void HID_Device_ProcessControlPacket(USB_ClassInfo_HID_Device_t* const HIDInterf case REQ_SetIdle: if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { - Endpoint_ClearSETUP(); - - HIDInterfaceInfo->State.IdleCount = ((USB_ControlRequest.wValue >> 8) << 2); - - while (!(Endpoint_IsINReady())); - Endpoint_ClearIN(); + if ((USB_ControlRequest.wIndex == HIDInterfaceInfo->Config.InterfaceNumber) || + (USB_ControlRequest.wValue & 0xFF) == 0) + { + Endpoint_ClearSETUP(); + + HIDInterfaceInfo->State.IdleCount = ((USB_ControlRequest.wValue & 0xFF00) >> 6); + + while (!(Endpoint_IsINReady())); + Endpoint_ClearIN(); + } } break; diff --git a/LUFA/Drivers/USB/LowLevel/DevChapter9.c b/LUFA/Drivers/USB/LowLevel/DevChapter9.c index f49f5b39b2..2318216469 100644 --- a/LUFA/Drivers/USB/LowLevel/DevChapter9.c +++ b/LUFA/Drivers/USB/LowLevel/DevChapter9.c @@ -174,59 +174,65 @@ void USB_Device_GetConfiguration(void) Endpoint_ClearOUT(); } -static void USB_Device_GetDescriptor(void) +#if !defined(NO_INTERNAL_SERIAL) && (defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)) +static void USB_Device_GetInternalSerialDescriptor(void) { - void* DescriptorPointer; - uint16_t DescriptorSize; + struct + { + USB_Descriptor_Header_t Header; + int16_t UnicodeString[12]; + } SignatureDescriptor; - #if !defined(NO_INTERNAL_SERIAL) && (defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)) - if (USB_ControlRequest.wValue == ((DTYPE_String << 8) | USE_INTERNAL_SERIAL)) + uint8_t SigReadAddress = 0x0E; + bool OddNibbleRead = false; + + #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) + SignatureDescriptor.Header.Size = sizeof(SignatureDescriptor); + SignatureDescriptor.Header.Type = DTYPE_String; + #else + SignatureDescriptor.Header.bLength = sizeof(SignatureDescriptor); + SignatureDescriptor.Header.bDescriptorType = DTYPE_String; + #endif + + for (uint8_t SerialCharNum = 0; SerialCharNum < 12; SerialCharNum++) { - struct - { - USB_Descriptor_Header_t Header; - int16_t UnicodeString[12]; - } SignatureDescriptor; - - #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) - SignatureDescriptor.Header.Size = sizeof(SignatureDescriptor); - SignatureDescriptor.Header.Type = DTYPE_String; - #else - SignatureDescriptor.Header.bLength = sizeof(SignatureDescriptor); - SignatureDescriptor.Header.bDescriptorType = DTYPE_String; - #endif + uint8_t SerialByte = boot_signature_byte_get(SigReadAddress); - uint8_t SigReadAddress = 0x0E; - bool OddRead = false; - - for (uint8_t SerialCharNum = 0; SerialCharNum < 12; SerialCharNum++) + if (OddNibbleRead) { - uint8_t SerialByte = boot_signature_byte_get(SigReadAddress); - - if (OddRead) - { - SerialByte >>= 4; - SigReadAddress++; - } - else - { - SerialByte &= 0x0F; - } - - OddRead = !(OddRead); - - if (SerialByte < 0x0A) - SerialByte += '0'; - else - SerialByte += ('A' - 0x0A); - - SignatureDescriptor.UnicodeString[SerialCharNum] = SerialByte; + SerialByte >>= 4; + SigReadAddress++; + } + else + { + SerialByte &= 0x0F; } - Endpoint_ClearSETUP(); - Endpoint_Write_Control_Stream_LE(&SignatureDescriptor, sizeof(SignatureDescriptor)); - Endpoint_ClearOUT(); + OddNibbleRead = !(OddNibbleRead); + + if (SerialByte < 0x0A) + SerialByte += '0'; + else + SerialByte += ('A' - 0x0A); + + SignatureDescriptor.UnicodeString[SerialCharNum] = SerialByte; + } + + Endpoint_ClearSETUP(); + Endpoint_Write_Control_Stream_LE(&SignatureDescriptor, sizeof(SignatureDescriptor)); + Endpoint_ClearOUT(); +} +#endif +static void USB_Device_GetDescriptor(void) +{ + void* DescriptorPointer; + uint16_t DescriptorSize; + + #if !defined(NO_INTERNAL_SERIAL) && (defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)) + if (USB_ControlRequest.wValue == ((DTYPE_String << 8) | USE_INTERNAL_SERIAL)) + { + USB_Device_GetInternalSerialDescriptor(); return; } #endif diff --git a/LUFA/Drivers/USB/LowLevel/DevChapter9.h b/LUFA/Drivers/USB/LowLevel/DevChapter9.h index fdef727578..2640cbba1a 100644 --- a/LUFA/Drivers/USB/LowLevel/DevChapter9.h +++ b/LUFA/Drivers/USB/LowLevel/DevChapter9.h @@ -99,6 +99,10 @@ static void USB_Device_GetDescriptor(void); static void USB_Device_GetStatus(void); static void USB_Device_ClearSetFeature(void); + + #if !defined(NO_INTERNAL_SERIAL) && (defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)) + static void USB_Device_GetInternalSerialDescriptor(void); + #endif #endif #endif diff --git a/LUFA/ManPages/ChangeLog.txt b/LUFA/ManPages/ChangeLog.txt index 1610059cc6..2281ca5953 100644 --- a/LUFA/ManPages/ChangeLog.txt +++ b/LUFA/ManPages/ChangeLog.txt @@ -55,6 +55,7 @@ * - Fixed USB_Host_SendControlRequest() not re-suspending the USB bus when initial device ready-wait fails * - Fixed USB Pad regulator not being disabled on some AVR models when the USB_OPT_REG_DISABLED option is used * - Fixed Host mode to Device mode UID change not causing a USB Disconnect event when a device was connected + * - Fixed Mouse/Keyboard demos not performing the correct arithmetic on the Idle period at the right times (thanks to Brian Dickman) * * * \section Sec_ChangeLog090605 Version 090605