Updated to support kernel 4.15.x, tested on Arch Linux with Kernel 4.15.7 and 4.15.8 (dkms)
This commit is contained in:
parent
0d184a4ae1
commit
7de0457a85
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 4.2.1, 2017-02-28T17:11:18. -->
|
<!-- Written by QtCreator 4.5.1, 2018-03-13T11:54:21. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
|
73
perixxkbd.c
73
perixxkbd.c
@ -149,6 +149,9 @@ struct usb_kbd {
|
|||||||
unsigned char *leds;
|
unsigned char *leds;
|
||||||
dma_addr_t new_dma;
|
dma_addr_t new_dma;
|
||||||
dma_addr_t leds_dma;
|
dma_addr_t leds_dma;
|
||||||
|
|
||||||
|
spinlock_t leds_lock;
|
||||||
|
bool led_urb_submitted;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void usb_kbd_irq(struct urb *urb)
|
static void usb_kbd_irq(struct urb *urb)
|
||||||
@ -315,47 +318,66 @@ resubmit:
|
|||||||
|
|
||||||
static int usb_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
|
static int usb_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
struct usb_kbd *kbd = input_get_drvdata(dev);
|
struct usb_kbd *kbd = input_get_drvdata(dev);
|
||||||
|
|
||||||
if (type != EV_LED)
|
if (type != EV_LED)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&kbd->leds_lock, flags);
|
||||||
kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
|
kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
|
||||||
(!!test_bit(LED_COMPOSE, dev->led) << 3) |
|
(!!test_bit(LED_COMPOSE, dev->led) << 3) |
|
||||||
(!!test_bit(LED_SCROLLL, dev->led) << 2) |
|
(!!test_bit(LED_SCROLLL, dev->led) << 2) |
|
||||||
(!!test_bit(LED_CAPSL, dev->led) << 1) |
|
(!!test_bit(LED_CAPSL, dev->led) << 1) |
|
||||||
(!!test_bit(LED_NUML, dev->led));
|
(!!test_bit(LED_NUML, dev->led));
|
||||||
|
|
||||||
if (kbd->led->status == -EINPROGRESS)
|
if (kbd->led_urb_submitted){
|
||||||
|
spin_unlock_irqrestore(&kbd->leds_lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (*(kbd->leds) == kbd->newleds)
|
if (*(kbd->leds) == kbd->newleds){
|
||||||
|
spin_unlock_irqrestore(&kbd->leds_lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
*(kbd->leds) = kbd->newleds;
|
*(kbd->leds) = kbd->newleds;
|
||||||
|
|
||||||
kbd->led->dev = kbd->usbdev;
|
kbd->led->dev = kbd->usbdev;
|
||||||
if (usb_submit_urb(kbd->led, GFP_ATOMIC))
|
if (usb_submit_urb(kbd->led, GFP_ATOMIC))
|
||||||
pr_err("usb_submit_urb(leds) failed\n");
|
pr_err("usb_submit_urb(leds) failed\n");
|
||||||
|
else
|
||||||
|
kbd->led_urb_submitted = true;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&kbd->leds_lock, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_kbd_led(struct urb *urb)
|
static void usb_kbd_led(struct urb *urb)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
struct usb_kbd *kbd = urb->context;
|
struct usb_kbd *kbd = urb->context;
|
||||||
|
|
||||||
if (urb->status)
|
if (urb->status)
|
||||||
hid_warn(urb->dev, "led urb status %d received\n",
|
hid_warn(urb->dev, "led urb status %d received\n", urb->status);
|
||||||
urb->status);
|
|
||||||
|
|
||||||
if (*(kbd->leds) == kbd->newleds)
|
spin_lock_irqsave(&kbd->leds_lock, flags);
|
||||||
|
|
||||||
|
if (*(kbd->leds) == kbd->newleds){
|
||||||
|
kbd->led_urb_submitted = false;
|
||||||
|
spin_unlock_irqrestore(&kbd->leds_lock, flags);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
*(kbd->leds) = kbd->newleds;
|
*(kbd->leds) = kbd->newleds;
|
||||||
kbd->led->dev = kbd->usbdev;
|
|
||||||
|
|
||||||
if (usb_submit_urb(kbd->led, GFP_ATOMIC))
|
kbd->led->dev = kbd->usbdev;
|
||||||
|
if (usb_submit_urb(kbd->led, GFP_ATOMIC)){
|
||||||
hid_err(urb->dev, "usb_submit_urb(leds) failed\n");
|
hid_err(urb->dev, "usb_submit_urb(leds) failed\n");
|
||||||
|
kbd->led_urb_submitted = false;
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&kbd->leds_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_kbd_open(struct input_dev *dev)
|
static int usb_kbd_open(struct input_dev *dev)
|
||||||
@ -378,20 +400,15 @@ static void usb_kbd_close(struct input_dev *dev)
|
|||||||
|
|
||||||
static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
|
static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
|
||||||
{
|
{
|
||||||
kbd->irq = usb_alloc_urb(0, GFP_KERNEL);
|
if (!(kbd->irq = usb_alloc_urb(0, GFP_KERNEL)))
|
||||||
if (!kbd->irq)
|
|
||||||
return -1;
|
return -1;
|
||||||
kbd->led = usb_alloc_urb(0, GFP_KERNEL);
|
if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL)))
|
||||||
if (!kbd->led)
|
|
||||||
return -1;
|
return -1;
|
||||||
kbd->new = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &kbd->new_dma);
|
if (!(kbd->new = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &kbd->new_dma)))
|
||||||
if (!kbd->new)
|
|
||||||
return -1;
|
return -1;
|
||||||
kbd->cr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
|
if (!(kbd->cr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
|
||||||
if (!kbd->cr)
|
|
||||||
return -1;
|
return -1;
|
||||||
kbd->leds = usb_alloc_coherent(dev, 1, GFP_ATOMIC, &kbd->leds_dma);
|
if (!(kbd->leds = usb_alloc_coherent(dev, 1, GFP_ATOMIC, &kbd->leds_dma)))
|
||||||
if (!kbd->leds)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -427,6 +444,7 @@ static int usb_kbd_probe(struct usb_interface *iface, const struct usb_device_id
|
|||||||
|
|
||||||
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
|
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
|
||||||
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
|
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
|
||||||
|
|
||||||
kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL);
|
kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL);
|
||||||
input_dev = input_allocate_device();
|
input_dev = input_allocate_device();
|
||||||
if (!kbd || !input_dev)
|
if (!kbd || !input_dev)
|
||||||
@ -437,6 +455,7 @@ static int usb_kbd_probe(struct usb_interface *iface, const struct usb_device_id
|
|||||||
|
|
||||||
kbd->usbdev = dev;
|
kbd->usbdev = dev;
|
||||||
kbd->dev = input_dev;
|
kbd->dev = input_dev;
|
||||||
|
spin_lock_init(&kbd->leds_lock);
|
||||||
|
|
||||||
if (dev->manufacturer)
|
if (dev->manufacturer)
|
||||||
strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name));
|
strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name));
|
||||||
@ -453,7 +472,7 @@ static int usb_kbd_probe(struct usb_interface *iface, const struct usb_device_id
|
|||||||
le16_to_cpu(dev->descriptor.idVendor),
|
le16_to_cpu(dev->descriptor.idVendor),
|
||||||
le16_to_cpu(dev->descriptor.idProduct));
|
le16_to_cpu(dev->descriptor.idProduct));
|
||||||
|
|
||||||
printk("<1>perixxkbd: detected %s\n", kbd->name);
|
printk("perixxkbd: detected %s\n", kbd->name);
|
||||||
|
|
||||||
usb_make_path(dev, kbd->phys, sizeof(kbd->phys));
|
usb_make_path(dev, kbd->phys, sizeof(kbd->phys));
|
||||||
strlcat(kbd->phys, "/input0", sizeof(kbd->phys));
|
strlcat(kbd->phys, "/input0", sizeof(kbd->phys));
|
||||||
@ -473,7 +492,6 @@ static int usb_kbd_probe(struct usb_interface *iface, const struct usb_device_id
|
|||||||
|
|
||||||
for (i = 0; i < 255; i++)
|
for (i = 0; i < 255; i++)
|
||||||
set_bit(px_kbd_keycode[i], input_dev->keybit);
|
set_bit(px_kbd_keycode[i], input_dev->keybit);
|
||||||
|
|
||||||
clear_bit(0, input_dev->keybit);
|
clear_bit(0, input_dev->keybit);
|
||||||
|
|
||||||
input_dev->event = usb_kbd_event;
|
input_dev->event = usb_kbd_event;
|
||||||
@ -490,7 +508,6 @@ static int usb_kbd_probe(struct usb_interface *iface, const struct usb_device_id
|
|||||||
kbd->cr->bRequest = 0x09;
|
kbd->cr->bRequest = 0x09;
|
||||||
kbd->cr->wValue = cpu_to_le16(0x200);
|
kbd->cr->wValue = cpu_to_le16(0x200);
|
||||||
kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);
|
kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);
|
||||||
//kbd->cr->wIndex = cpu_to_le16(0);
|
|
||||||
kbd->cr->wLength = cpu_to_le16(1);
|
kbd->cr->wLength = cpu_to_le16(1);
|
||||||
|
|
||||||
usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
|
usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
|
||||||
@ -523,6 +540,7 @@ static void usb_kbd_disconnect(struct usb_interface *intf)
|
|||||||
if (kbd) {
|
if (kbd) {
|
||||||
usb_kill_urb(kbd->irq);
|
usb_kill_urb(kbd->irq);
|
||||||
input_unregister_device(kbd->dev);
|
input_unregister_device(kbd->dev);
|
||||||
|
usb_kill_urb(kbd->led);
|
||||||
usb_kbd_free_mem(interface_to_usbdev(intf), kbd);
|
usb_kbd_free_mem(interface_to_usbdev(intf), kbd);
|
||||||
kfree(kbd);
|
kfree(kbd);
|
||||||
}
|
}
|
||||||
@ -530,6 +548,8 @@ static void usb_kbd_disconnect(struct usb_interface *intf)
|
|||||||
|
|
||||||
static struct usb_device_id usb_kbd_id_table [] = {
|
static struct usb_device_id usb_kbd_id_table [] = {
|
||||||
{ USB_DEVICE(ML_VENDOR_ID, ML_PRODUCT_ID) },
|
{ USB_DEVICE(ML_VENDOR_ID, ML_PRODUCT_ID) },
|
||||||
|
{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
|
||||||
|
USB_INTERFACE_PROTOCOL_KEYBOARD) },
|
||||||
{ } /* Terminating entry */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -547,8 +567,9 @@ static int __init usb_kbd_init(void)
|
|||||||
int result = usb_register(&usb_kbd_driver);
|
int result = usb_register(&usb_kbd_driver);
|
||||||
|
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
|
printk("perixxkbd: usb_register success\n");
|
||||||
DRIVER_DESC "\n");
|
else
|
||||||
|
printk("perixxkbd: usb_register failure\n");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user