Open Cyberwizzard opened 11 years ago
I've found those keystrokes don't work in Windows - I have no idea why. They work fine on Mac and are part of the USB HID specification. It's pretty weird. If you figure out a cross platform way to do the keys I'd be very interested.
I'd be quite interested to see if this works with linuxes - I'd expect them to support the standards, but if windows doesn't maybe it isn't a standard worth supporting.
Also I recommend you use millis rather than micros - I'm not sure, but I could imaging C choking on that number 1000000. If you change it to 1000000UL it should be okay. It just might try to cooerce it in to the default type of integer depending on it's mood otherwise.
I made sure that the inferred types actually match what I expected so the 10 second timer worked fine.
After debugging for a couple of days I resorted to using a USB packet sniffer to see what is going on. I found that the HID description is faulty as it defines the maximum scan code to be 0x65 which is fine for a standard 101 key layout but that does not include the special scan codes. By changing the maximum scan code to 130 (0x82) the DigiKeyboard library worked on Ubuntu linux.
0x25, 0x82, // LOGICAL_MAXIMUM (101) - edit Cyberwizzard: increase to 130 to include media keys 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x29, 0x82, // USAGE_MAXIMUM (Keyboard Application) - edit Cyberwizzard: increase to include media keys 0x81, 0x00, // INPUT (Data,Ary,Abs) 0xc0 // END_COLLECTION
I then connected a Logitech keyboard to see how media keys are transmitted. While I could get the HID descriptor, it was quite extensive. In the capture I could see that the normal keys and media keys used different end points (0x81 for normal key strokes and 0x82 for media keys).
I am now working on a composite device which should work on all platforms.
Update: I now have a composite device which acts like a keyboard with a media controller. It works fine under linux but Windows Vista & 7 seem to ignore the media keys (once again).
Edit: I modified my library to only advertise the Consumer controls which works fine under linux but once again not under Windows 7. I found an MSDN article stating that Win7&8 should recognize Consumer class input devices but it lists different drivers for the mouse+keyboard and customer classes. I bet I need a separate collection or even a separate device (not classed as a keyboard) to make it work on Windows.
At this point I am not really interested to go the last mile and create the Windows 7 compatible HID as that would most likely mean that I would lose normal keyboard input...
Oh well. I don't really care so much - I only use windows for games. I'm sure you could set it to send function keys like f13 and use some program to map it across. I currently use something like that to make the mute "press in" mode pause itunes instead of system wide mute as in the code here
I wonder if this setting change would work? http://forums.logitech.com/t5/G-Series-Gaming-Keyboards/G15-Media-Keys-and-mute-button-not-working-in-windows-7/td-p/341605
From what i can gather to enable multimedia buttons in windows you need to configure it as a Consumer control device.
In order to control the device as determined by the media control keys was used corresponding USBHidReportDescriptor, taken from the USB descriptor multimedia keyboards, and writing the appropriate handling code.
Example USB descriptor PROGMEM char usbHidReportDescriptor [25] = {/ * USB report descriptor * / 0x05, 0x0c, / ??/ ??USAGE_PAGE (Consumer Devices) 0x09, 0x01, / / ??USAGE (Consumer Control) 0xa1, 0x01, / / ??COLLECTION (Application) 0x85, 0x01, / / ??REPORT_ID (1) 0x19, 0x00, / / ??USAGE_MINIMUM (Unassigned) 0x2a, 0x3c, 0x02, / / ??USAGE_MAXIMUM (AC Format) 0x15, 0x00, / / ??LOGICAL_MINIMUM (0) 0x26, 0x3c, 0x02, / / ??LOGICAL_MAXIMUM (572) 0x95, 0x01, / / ??REPORT_COUNT (1) 0x75, 0x10, / / ??REPORT_SIZE (16) 0x81, 0x00, / / ??INPUT (Data, Var, Abs) 0xc0 / / END_COLLECTION};
That was taken from http://obruboff.ru/usb-volume-control-ver-2/ which uses V-USB an ATTiny 85
I have build the circuit from the link above and it works great but its nice to have a bootloader as in the digispark.
Consumer Device Codes http://msdn.microsoft.com/en-us/windows/hardware/gg462991.aspx
MUTE 0xe2 VOLUME DOWN 0xea VOLUME UP 0xe9
The V-USB MAME panel example has joystick,keyboard and consumer device in its USBHidReportDescriptor this also includes volume control http://vusb.wikidot.com/project:mamepanel
Any chance we could have a digispark consumer device library with the volume control as an example, as its pretty useful. Its a bit beyond me I have no hair left :)
Thanks
Rupert
You could make one! Like I said above, I can't be bothered. I don't think it's good to make things that you don't intend to use frequently yourself. I'd have no incentive to maintain code like that.
Not working for me too !!
I know this is an old code but to make it work anywhere use the Trinket HID library (which is also old, but not as old): https://learn.adafruit.com/trinket-usb-volume-knob/add-a-mute-button
Just copy that code. Since my digispark is the typical aliexpress clone (https://s.click.aliexpress.com/e/_dVwsVW7) pin 3, 4, 5 were not usable (3 and 4 are the bitbanged USB and 5 is tied to reset). So what you have to do is remove the led in the center of the board and use pin 1 for the button, following the adafruit code.
PS: Also you need an old USB port or hub (does not work on most modern USB 3.x ports for some reason in my docking station)
Really cool to see someone still making use of this! Hope you find the knob useful 💙
Do I need a special version of the keyboard controller or should the Arduino 1.0.4 from the wiki suffice for this example? I do not have the rotary encoder so I am trying to send the mute or volume commands to my computer but it does not seem to respond.
I tried with an without the null key stroke but it does not seem to matter to my PC or laptop.
include "DigiKeyboard.h"
define KEY_MUTE 127
define KEY_VOLUME_UP 128
define KEY_VOLUME_DOWN 129
unsigned long time = 0;
void setup() {
time = micros(); DigiKeyboard.update(); }
void press_button() { //DigiKeyboard.sendKeyStroke(0); //this is generally not necessary but with some older systems it seems to prevent missing the first character after a delay //DigiKeyboard.sendKeyStroke(KEY_MUTE); DigiKeyboard.sendKeyStroke(KEY_VOLUME_DOWN); }
void loop() { DigiKeyboard.update();
unsigned long time_now = micros(); if((time_now-time) > 1000000) { press_button(); time = micros(); } }