Saturday, September 13, 2014

Azio L70 Keyboard Linux Driver, The Implementation

Implementing the Azio Driver

At this point I was ready implementing the Azio driver, so I copied usbkbd.c to a file called aziokbd.c and began making edits there. I left the driver in drivers/hid/usbhid to make compiling easier. Obviously I changed the script from last time to work with a module named aziokbd instead of usbkbd.

This is where developing in a virtual machine had a hidden benefit. I could easily toggle the USB passthru from the VirtualBox menu and thereby simulate plugging and unplugging the keyboard from the guest machine. Unfortunately this hid a problem from me that I will get to later.

To implement the driver, I just had to change the lines in usb_kbd_irq to report the correct keycodes for the bytes coming in from the hardware with input_report_key. I already had the pattern worked out from reverse engineering the protocol with wireshark and usbmon.

The Azio keyboard breaks the keys up into three chunks. When the first byte in the array is 01, it is a volume control. When it is 04, that is a “regular” key like a-z, 0-9, etc… Finally, a 05 indicates the function keys and numpad. In the driver I simply broke these three cases out into their own respective if/else if branches. Since the volume only has two controls (up and down) I did not do anything fancy and just implemented them naively. For the other two cases I used the bitmasking trick and went through the remaining 7 bytes in the array.

The real trick was setting up the keycodes in the usb_kbd_keycode array such that with a little math I could easily correspond an incoming bit with the outgoing keycode. I did that by arranging the keycodes into 8 rows of 8. The first 64 elements were for byte arrays starting with 04, the second 64 were for byte arrays starting with 05 and the rest remains unused (other than the two volume keys).

With the keycodes structured this way I could index into the array by taking the position of each bit and multiplying it by it by the position of the byte I was inspecting. For 05 keys, I just had to offset the indexing by 64 to move to the next 8x8 block in the array.

Using the Driver

Once that was complete I was able to compile and begin using my driver. As a matter of fact, I was already using the driver by this point. About the last half of the driver development was done with the Azio keyboard and my driver. Whenever I encountered a key that was not yet implemented I used the secondary keyboard. That would cause enough pain to implement the key. The implementation outlined above was the result of some refactoring and not the original algorithm. The only thing left was to get the LEDs for the lock keys working.

This was a pretty exhilarating milestone in my little project. At this point I ditched the VM and moved development to my workstation proper. This was when I discovered a second thing that was not working right. This is the issue I was referring to earlier, that the VM hid from me. The generic usbhid driver was always grabbing the keyboard first and the azio driver was not loading. Even after running modprobe aziokbd, my driver was not getting access to the physical device.

ZOMG! Quirks are Quirky

This turned into a massive time sink. It is one that I am not sure I have escaped even to this day. If you search online for blacklisting a USB device you will find a lot of other people searching online for how to blacklist a USB device. Nobody really seems to know. In fact there appear to be two ways of doing depending on if the driver is compiled into the kernel or as a module. What you will find is that there is this thing called USB quirks. What you will not find is a consistent, well documented, and clear way to apply a “quirk”.

Unfortunately, even though I have got this working, it still feel as though I do not have it nailed down. Blacklisting works passing a option to the usbhid driver called “quirks”. The first part of the option’s value is the 16-bit USB vendor id, the second part is the 16-bit product id and third part is the “the u32 quirks value”. You can read the sum total of the documentation on this, that exists in the entire world, on lines 178-188 of hid-quirks.c. What are the valid u32 quirks values and what do the values mean? Apparently nobody knows. If you know where they are documented, please email me. I would very much like to know. There are just faint whispers on the wind that this is how you do it and some people have had success.

The USB vendor and product ids are easily obtained by running lsusb -v and finding your device (assuming it is plugged in). Many places on the web will tell you that the magic number is 0x0004. I am here to emphatically tell you that 0x0004 DOES NOT WORK… EXCEPT WHEN IT DOES!. Honestly, at this point I do not know what to tell anyone.

In sum, the command looks like this:


You can pass it to the driver on the commandline by placing it after the driver name when calling modprobe, like so:

sudo modprobe usbhid quirks=0x0c45:0x7603:[MAGIC_NUMBER]

Since the usbhid driver will already be loaded, the full command is:

sudo rmmod usbhid && sudo modprobe usbhid quirks=0x0c45:0x7603:[MAGIC_NUMBER]

This is a good way to test it out and make sure that you have the quirk right, but eventually you will want this thing to just work at boot up. To do that, you put the quirks into file in /etc/modprobe.d. I created the file usbhid.conf with the following contents:

options usbhid quirks=0x0c45:0x7603:[MAGIC_NUMBER]

Here is the weird and confusing part. On my VM I had success with the magic number of 0x0007. To this day I can go back through my bash command history and see where I issued it many times. Furthermore, if I look at my /etc/modprobe.d/usbhid.conf it has the following line:

options usbhid quirks=0x0c45:0x7603:0x0007

It is working on my VM as I write this. I can passthru the L70 keyboard and reboot the VM and it works.

Transitioning to the Workstation

For some reason when I switched to my development workstation the quirk was not working. At that point I just sort of gave up. I would just load the driver with the commandline (except it was slightly more complicated because I had to also unload and load my mouse driver) and then sleep my machine.

Eventually that became a hassle and I got tired of having two keyboards attached to the computer and I sat down one night with the goal of solving it once and for all. I spent another several hours searching and loading and tweaking before I was ready to give up. I thought why does this work on the VM and not my desktop? Although I swear I copied the original file from the VM, I thought it time to compare the two. Sure enough I noticed the magic number was different. So my workstation’s /etc/modprobe.d/usbhid.conf looked like this:

options usbhid quirks=0x0c45:0x7603:0x0004 

I never did notice that I was using 0x0007 on the commandline but the file was using 0x0004. When I changed the four to seven it suddenly started working.

I know you are thinking at this point you are kind of an idiot, but to this day I am sure that I would have started from the same working point on the VM and that I only began researching a second time when it did not work. However, I cannot rule out the notion that I put that stupid 4 in there to begin with and that was the problem the whole time.

Damn you Quirks!

Now here is where it gets interesting. The other day I upgraded to kernel 3.13.0-15 and my keyboard stopped working. Although I had much better things to do that night I spent the evening trying to figure out why, hours went by and I felt like it was groundhog’s day. But this time was a little different. Nothing would let me load that driver. I never figured it out and finally went to bed.

The next day I saw there were updates and one of them was a new kernel, 3.13.0-16. I installed, rebuilt the driver and loaded it, but the keyboard was still not working. Looking at the dmesg trace I could see that the usbhid driver was grabbing it before the azio driver was loaded. This was not supposed to be happening with the quirk in the config file. Since I only rebooted about 700 times in the last two days I figured What the heck? I will change that seven to a four. It’s about the only thing I haven’t tried. You already know it worked, right? So here I am, typing this blog post with a usbhid.conf that looks like this:

swoogan@workstation:~$ cat /etc/modprobe.d/usbhid.conf 
#options usbhid quirks=0x0c45:0x7603:0x0007
options usbhid quirks=0x0c45:0x7603:0x0004

Let’s just say I am waiting for the day where I will be switching those two around. I still find it hard to believe that the command that did not work now works and that I have two different quirks on the two machines. It is worth noting that the VM uses a much older kernel.

Lighting up the LEDs

Figuring out the LEDs was a little tricky. Again I did not know where in the driver that I should be looking at. There are a couple of places where the constants LED_NUML, LED_CAPSL, and LED_SCROLLLare used so I littered the area with printk statements. After more and more printk statements and toggling the lock keys a few dozen times, I narrowed it down to the line kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);. It seemed that desc.bInterfaceNumberwas not holding the value that should be passed in. After little more tinkering, I got the LEDs to work by simply hardcoding 0 instead. The final line is

kbd->cr->wIndex = cpu_to_le16(0);

I will be honest and say that I do not know why that works or if it really does work in all cases. But it seems to work.

Building the Driver “Out of Tree”

To build a Linux driver outside of the kernel source tree you just need an appropriate makefile. I just created a folder in my standard development area on my machine for the Azio driver. I then moved my aziokbd.c file into it and created a Makefile. To be honest, I shamelessly copied someone else’s makefile. I do not even remember where I got it from.

The only thing I did was changed whatever was in obj-m to be aziokbd.o and added an install target:

    cp aziokbd.ko /lib/modules/$(shell uname -r)/kernel/drivers/input/keyboard
    echo 'aziokbd' >> /etc/modules

Final Steps

Now we get to today. I am using my Azio L70 keyboard daily and quiet enjoying the fact that I wrote the driver for it. However, there are two tasks I still have to work on:

  1. Fix the Meta key. It was working but has recently stopped functioning.
  2. DKMS

DKMS is dynamic kernel module support, which is a way for source code modules to be built dynamically when a new kernel is installed. If your module is not in the kernel, it is not included with system updates. If you have built it from source, it only gets built for a specific version of the kernel. This means that without DKMS you have to rebuild it every time you do a kernel upgrade. In my case it is particularly cumbersome because my keyboard is blacklisted from the generic usbhid, so after a kernel update it stops working.

If you are interested, check out the driver project page.

You can clone the repostoriy with:

hg clone


  1. Thank you so much! I am typing this on my Kubuntu box with an Azio L70 keyboard, with newly working modifier keys! The module worked perfectly after I followed your README instructions and ran
    sudo modprobe aziokbd
    sudo rmmod usbhid && sudo modprobe usbhid quirks=0x0c45:0x7603:0x0007

  2. Awesome! I'm glad it works on your machine as well. I just added DKMS support last night, so you might want to get that version if you haven't already.

  3. Colin, much thanks for sharing your efforts. My keyboard selection process was much like yours', along with your initial disappointment.

    After several tries I could not get it to work and gave up. Today I thought I would give another try and happened on the fix by accident based on the order that I did things.

    Using xUbuntu 14.04 LTE (kernel 3.13.0-24-generic) the quirks stuff seems to be unnecessary, both 0x0007 & 0x0004 and/or removing usbhid.conf all work the same... i.e. the below worked for me (as root)

    modprobe aziokbd
    rmmod usbhid && modprobe usbhid

    But only if I unplug and replug the keyboard after usbhid is restarted.

    It seems that "usbhid: USB HID core driver" always loads 1st, before the aziokbd module loads and they don't seem to talk properly unless usbhid is restarted after aziokbd has loaded AND then the keyboard needs to be plugged in, IN THAT ORDER. If the keyboard is connected at boot restarting usbhid has no effect as the initial bind seems to be remembered even after usbhid is restarted. So, I did some scripting that allows me to reset the usb ports at startup, without actually disconnecting the keyboard. Happy to report I am typing this message from the Azio keyboard.

    Pity that Azio didn't bother to do this themselves... it really reflects poorly on them as a company that they would ignore such a large and growing user base. Maybe you should offer to sell them the driver? ;-)

    1. Peter,

      Thanks for your feedback. Your experience with the quirks setting is consistent with the madness I had trying to get it to work. It seems to be really flaky. You might even find that it suddenly works with your next kernel update.

      In my travels I found that the usbhid driver always loads first, it always grabs the keyboard and it's tricky to work around that. I'm not sure if this will work for you (or if it even matters at this point), but a good place to start with all of this is with the commands:

      sudo rmmod usbhid; sudo modprobe aziokbd; sudo modprobe usbhid

      This drops the usbhid driver and loads aziokbd driver. Once it's grabbed the device, usbhid can't.

      I had much the same thoughts in terms of Azio. I did contact them regarding the driver, but they didn't seem inclined to support it, let alone purchase it. I decided it was worth more to me to retain authorship. Although, I did have visions of a couple sweet mechanical keyboards showing up!

  4. Colin,

    Well, you seem to grasp my issues, but for one small detail. What you suggested is in effect what I am doing ... in rc.local I added

    rmmod usbhid && modprobe usbhid

    but by itself, this will only cause the keyboard to stop working altogether. That is until it is unplugged and reconnected OR if the USB ports are reinitialized. The aziokbd driver is already loaded as per your implementation instructions from module startup in:


    And verified by looking at dmesg. So, I found a useful script that iterates through the USB device folder, resetting the device bindings.

    if [[ $EUID != 0 ]] ; then
    echo This must be run as root!
    exit 1
    for xhci in /sys/bus/pci/drivers/?hci_hcd ; do
    if ! cd $xhci ; then
    echo Weird error. Failed to change directory to $xhci
    exit 1
    echo Resetting devices from $xhci...
    for i in ????:??:??.? ; do
    echo -n "$i" > unbind
    echo -n "$i" > bind

    Again, this is run as part of rc.local on startup, after usbhid is reset. As long as all this happens after aziokbd has loaded it works fine.

    Now I wonder, if I could add to your C code, some logic that would look for the keyboard and reset it's port as part if it's init subroutine. Then installation would be a fire and forget operation. Hmmmm, just a thought. But like you, I know a half dozen versions of basic, a dozen different scripting languages, C will be a new on for me... ;-)

  5. Hmm - I hit preview, and my comment just disappeared - hope I'm not double posting!

    INFO: I purchased a Gambias Ares gaming keyboard, and plugged it into a Debian Jessie box. Ctrl, Alt, Fn, and Windows keys all seem to mapped to shift. The keyboard identifies as 0c45:7603 Microdia

    It appears that your driver should solve that problem. There is precious little on the internet that offers any other solution!

    For some reason, I thought your page offered a Ubuntu-centric driver, but on reading it all again, I see that it is indeed a "Linux driver".

    Here goes nothing . . .

    1. Oh - from your bitbucket page, "NOTE: Makefile and instructions are only tested on Ubuntu." Hmmm - I guess I'll find out if the driver is agreeable with Jessie!

    2. Well - no joy here today.

      guy@sparky:~$ inxi
      CPU~Dual core AMD Opteron 165 (-MCP-) clocked at 1808 Mhz Kernel~3.19-3.dmz.1-liquorix-amd64 x86_64 Up~ Mem~763.3/3139.4MB HDD~560.1GB(54.1% used) Procs~158 Client~Shell inxi~2.1.28

      I have tried both the 0x0004 and the 0x0o07 quirks, without luck. I can't know whether there is a problem with Jessie, with the Liquorix kernel, or what. I'm just kinda stuck right now. Luckily, I have a couple working keyboards, so I'm not in a real jam here. I'm just a little aggravated is all. Maybe I'll come back to this in a few hours - maybe in a couple days.

    3. Errrrrr - waitasecondhere! Is Magic Number supposed to be in brackets? I am accustomed to REMOVING the brackets and/or parenthesis when typing commands. Hmmm . . . . nope, I found another discussion regarding azio.kbd driver, and the brackets aren't in use.

      However, that link suggests putting the quirk into grub's startup. I'm a bit lost on that idea.

  6. GOT IT!!!! YES!! Edit /etc/default/grub
    GRUB_CMDLINE_LINUX_DEFAULT="quiet usbhid.quirks=0x0c45:0x7603:0x4"

    Run "update-grub" and reboot.

    The keys all seem to be working properly now. I don't know how long they'll work - I used the DKMS install option, so it should all continue working even after a kernel update. I'm bookmarking this page, and I've also subscribed to this discussion. Hopefully, I've helped someone! I know you've helped me!!

    1. That's so awesome that you were able to figure it out. Your persistence is admirable.

      It is really cool to find out that the driver works with other keyboards too. I'm not surprised that it works with Debian since Ubuntu is derived from it. I just don't have the resources to test on anything besides what I'm running.

      It looks like magic number 4 is working for you. I knew about the grub method (I actually vague allude to the fact that there are two ways to implement the quirks in the post). What I understand is that the grub method is for when your usbhid driver is compiled into the kernel and the modprobe/usbhid.conf is for when the driver is compiled as a module. Since I had no way to test the former, I didn't want to say too much about it.

  7. LOL, you call it persistence. My mama called it stubborn.

    I suppose that you can mark your driver as "tested on Debian Jessie", and you can certainly edit in the Grub fix. It's not like any of that is original work on my part - I found it in the community, and it's all community property! I should probably offer a link to where I found it - let me see if I can do that, it's in history . . . .

    It's difficult to see who posted what there - something wrong on with my configuration, I suppose. I think Sneetsher gets credit for that last post, which shows how to fix the problem with grub.

  8. You are fucking awesome! It's working on B-MOVE N8HAWK keyboard and Arch Linux out the box.

    Very good post too mate, very well explained, good job!

  9. This comment has been removed by a blog administrator.

  10. hello ,
    thanks a lot , it works perfectly with my px 1800 keyboard on debian 8 .
    Good job :D

  11. hi, how can i install this driver for my perixx 1800 on ubuntu? Which commands line please ?

    1. i tried to isnstall it by using the dkms and after the manual insstallation but my keyboard is not answering at all now can someone help me please.

    2. What do you get when you run 'lsmod'? Is the module loaded? You could try uninstalling the dkms module and installing it manually. Likely what happened is that the keyboard is successfully blacklisted by the usbhid driver, but the new driver isn't loading. You manually can load it with 'sudo modprobe aziokbd'. Also check your 'dmesg' for errors.

  12. GOT IT!!!! YES!! Edit /etc/default/grub
    GRUB_CMDLINE_LINUX_DEFAULT="quiet usbhid.quirks=0x0c45:0x7603:0x4"

    Run "update-grub" and reboot.

  13. This comment has been removed by the author.

  14. Sorry, hi, I've installed this driver on Linux Mint 17.2, and it works great apart from one thing. The backslash/pipe key on the English (US) QWERTY layout, just to the left of the enter key, doesn't work at all. I think somebody else mentioned a similar issue, but on a different keyboard layout, at Do you know if there is any way to fix this issue?

    1. Can you download the latest driver and uncomment lines 124-130? Using `dmesg` you can see what data is sent to the driver when you press your key. From there I can modify the driver to send the correct keycode.

    2. Hi,

      To fix the backslash/pipe key, change line 63 of aziokbd.c:


  15. HI
    Can you help me? I have same problem and your driver not working for me :(
    dmesg shows:
    [ 668.754102] usb 3-1.6: USB disconnect, device number 4
    [ 671.512898] usb 3-1.6: new low-speed USB device number 5 using ehci-pci
    [ 671.611395] usb 3-1.6: New USB device found, idVendor=1a2c, idProduct=002f
    [ 671.611400] usb 3-1.6: New USB device strings: Mfr=1, Product=2, SerialNumber=0
    [ 671.611403] usb 3-1.6: Product: USB Keyboard
    [ 671.611405] usb 3-1.6: Manufacturer: SEMICO
    [ 671.614973] input: SEMICO USB Keyboard as /devices/pci0000:00/0000:00:1a.0/usb3/3-1/3-1.6/3-1.6:1.0/0003:1A2C:002F.0005/input/input26
    [ 671.669484] hid-generic 0003:1A2C:002F.0005: input,hidraw2: USB HID v1.11 Keyboard [SEMICO USB Keyboard] on usb-0000:00:1a.0-1.6/input0
    [ 671.681307] input: SEMICO USB Keyboard as /devices/pci0000:00/0000:00:1a.0/usb3/3-1/3-1.6/3-1.6:1.1/0003:1A2C:002F.0006/input/input27
    [ 671.737527] hid-generic 0003:1A2C:002F.0006: input,hiddev0,hidraw3: USB HID v1.11 Keyboard [SEMICO USB Keyboard] on usb-0000:00:1a.0-1.6/input1

    Please :((

    1. You have a completely different chipset from mine. You would have to start by forking my driver and changing the lines:
      #define ML_VENDOR_ID 0x0c45
      #define ML_PRODUCT_ID 0x7603
      #define ML_VENDOR_ID 0x1a2c
      #define ML_PRODUCT_ID 0x002f

      From there I you need to either use usbmon and wireshark, or the driver to figure out the protocol (assuming it's different from the Microdia chipset).

    2. Thank you for reply:)

      Do you have some free time and could you spend some with me and collaborate to try fix this issue? I love my keyboard and my xubuntu :)

    3. Rafał,

      Sorry, my time has been limited lately. I suggest you thoroughly read all the articles in this series. It was my hope that in writing the articles I would have laid out all the necessary steps to accomplish what I did with the Azio keyboard. If you get started, I would be happy to help you with specific issues, since I have a bit of experience under my belt now.

  16. Hello,

    I`m having the same problem with a Serioux Radiant kbl-003 keyboard. I tried manually installing your driver on Linux Mint 17.3 64bit, it worked right after install, except the backslash and vertical line where replaced with the { and [. After reboot X crashes and I couldn`t make it work again (I`m kinda new to Linux).

    After that i tried running Xubuntu 14.04 32bit in Virtualbox, tried both the dkms and manual install but the driver is not loading.

    My dmesg reports:

    [ 3191.679886] usb 1-5: USB disconnect, device number 3
    [ 3192.447220] usb 1-5: new low-speed USB device number 5 using xhci_hcd
    [ 3192.559182] usb 1-5: Device not responding to setup address.
    [ 3192.763023] usb 1-5: Device not responding to setup address.
    [ 3192.966788] usb 1-5: device not accepting address 5, error -71
    [ 3237.930265] usb 1-5: new low-speed USB device number 7 using xhci_hcd
    [ 3238.063508] usb 1-5: New USB device found, idVendor=0c45, idProduct=7603
    [ 3238.063516] usb 1-5: New USB device strings: Mfr=1, Product=2, SerialNumber=0
    [ 3238.063521] usb 1-5: Product: USB Keyboard
    [ 3238.063524] usb 1-5: Manufacturer: SONiX
    [ 3238.063790] usb 1-5: ep 0x81 - rounding interval to 64 microframes, ep desc says 80 microframes
    [ 3238.063800] usb 1-5: ep 0x82 - rounding interval to 64 microframes, ep desc says 80 microframes
    [ 3238.066837] input: SONiX USB Keyboard as /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5:1.0/0003:0C45:7603.0004/input/input19
    [ 3238.122501] hid-generic 0003:0C45:7603.0004: input,hidraw0: USB HID v1.11 Keyboard [SONiX USB Keyboard] on usb-0000:00:14.0-5/input0
    [ 3238.130461] input: SONiX USB Keyboard as /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5:1.1/0003:0C45:7603.0005/input/input20

    How should I proceed? The vendor id and product id seem to match yours, would it need just an easy fix to work?

    Thanks for your time!

    1. Okay so everything works fine on Xubuntu 14.04 64 bit, besides the backslash/vertical line problem. Thank you very much for this driver! Please tell me how to fix the backslash issue.

    2. Lucian,

      Can you open an issue?


  17. Thanks a lot, man!
    It works for me!

  18. On Slackware64 14.2 doing 'make default' and then 'make install' works, avoiding the You also have to unload the usbhid module, load the aziokbd, load the usbhid, in that order.

    I had a thought though. After buying this keyboard (Gamdias Ares) and finding out for some retarded reason you need a non-standard driver for a keyboard and came across this driver, I was thinking of doing it through an X keymap. Until I get a real mechanical keyboard I did not want to give up typing on this Ares, it has a great feel for a membrane. I was wondering to avoid usbhid conflicts, would a userland driver be a better solution?

    Great work by the way and I thank you. I can imagine the effort you went through and you have done the community a great service.

    1. There is no way to do an X keymap. The usbhid driver reports the keycodes to the kernel, which relays them to userland. The keycodes are wrong. Usbhid is mapping 3 keys to one value. There is no way to map that one value back to three values. The information is lost.

  19. Hi Colin! First of all, man, thanks A MILLION for this driver man. It is awesome to see how your development took place in your blog posts. I'm really sad to see that the blog haven't had new material, it is definitely a addition to my rss.

    Anyway, going to the core of the problem... I'm speaking from Brazil! Here, there's a pc accessories manufacturer who sells a keyboard called Multilaser Warrior TC200. The damm thing runs the same cursed chip as your beloved keyboard. I was close to take the keyboard back to the store (I spend a substancial amount of money on this one), when I decided to look for the combo keys that aren't working, and then I've found your bitbucket.

    I would like to ask you for help with this man. I think your keyboard driver will work for my keyboard, but when running $lsusb, the ID of the device, before the microdia line is different from your Azio keyboard. Would this impact anything on the process you pointed on your's bitbucket readme? I really don't mind breaking things, so I can do and redo anything how many times I need to, but I would like to consult with you first.

    Could you help-me with this? You'll earn a place to stay on your next visit to Rio, it is a promise!

    btw, you can reach-me on gustavohmsilva[at]

  20. Hi, Colin.

    Your driver works fine on Genius Scorpion K9!

    Only two multimedia keys were not working, but with some time-consuming debugging, I got them working with this code:

    /* Refresh - M. */
    if (kbd->new[1] == 39 && kbd->old_01[1] != 39)
    input_report_key(kbd->dev, az_kbd_keycode[141], 1);
    if (kbd->old_01[1] == 39 && kbd->new[1] != 39)
    input_report_key(kbd->dev, az_kbd_keycode[141], 0);

    /* WWW - M. */
    if (kbd->new[1] == 148 && kbd->old_01[1] != 148)
    input_report_key(kbd->dev, az_kbd_keycode[148], 1);
    if (kbd->old_01[1] == 148 && kbd->new[1] != 148)
    input_report_key(kbd->dev, az_kbd_keycode[148], 0);



    Keys 141 (KEY_REFRESH) and 148 (KEY_WWW) are the new ones.