📄 ati_remote.c
字号:
/* * ati_remote_report_input */static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs){ struct ati_remote *ati_remote = urb->context; unsigned char *data= ati_remote->inbuf; struct input_dev *dev = ati_remote->idev; int index, acc; int remote_num; /* Deal with strange looking inputs */ if ( (urb->actual_length != 4) || (data[0] != 0x14) || ((data[3] & 0x0f) != 0x00) ) { ati_remote_dump(data, urb->actual_length); return; } /* Mask unwanted remote channels. */ /* note: remote_num is 0-based, channel 1 on remote == 0 here */ remote_num = (data[3] >> 4) & 0x0f; if (channel_mask & (1 << (remote_num + 1))) { dbginfo(&ati_remote->interface->dev, "Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n", remote_num, data[1], data[2], channel_mask); return; } /* Look up event code index in translation table */ index = ati_remote_event_lookup(remote_num, data[1], data[2]); if (index < 0) { dev_warn(&ati_remote->interface->dev, "Unknown input from channel 0x%02x: data %02x,%02x\n", remote_num, data[1], data[2]); return; } dbginfo(&ati_remote->interface->dev, "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", remote_num, data[1], data[2], index, ati_remote_tbl[index].code); if (ati_remote_tbl[index].kind == KIND_LITERAL) { input_regs(dev, regs); input_event(dev, ati_remote_tbl[index].type, ati_remote_tbl[index].code, ati_remote_tbl[index].value); input_sync(dev); ati_remote->old_jiffies = jiffies; return; } if (ati_remote_tbl[index].kind == KIND_FILTERED) { /* Filter duplicate events which happen "too close" together. */ if ((ati_remote->old_data[0] == data[1]) && (ati_remote->old_data[1] == data[2]) && ((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) { ati_remote->repeat_count++; } else { ati_remote->repeat_count = 0; } ati_remote->old_data[0] = data[1]; ati_remote->old_data[1] = data[2]; ati_remote->old_jiffies = jiffies; if ((ati_remote->repeat_count > 0) && (ati_remote->repeat_count < 5)) return; input_regs(dev, regs); input_event(dev, ati_remote_tbl[index].type, ati_remote_tbl[index].code, 1); input_event(dev, ati_remote_tbl[index].type, ati_remote_tbl[index].code, 0); input_sync(dev); return; } /* * Other event kinds are from the directional control pad, and have an * acceleration factor applied to them. Without this acceleration, the * control pad is mostly unusable. * * If elapsed time since last event is > 1/4 second, user "stopped", * so reset acceleration. Otherwise, user is probably holding the control * pad down, so we increase acceleration, ramping up over two seconds to * a maximum speed. The acceleration curve is #defined above. */ if ((jiffies - ati_remote->old_jiffies) > (HZ >> 2)) { acc = 1; ati_remote->acc_jiffies = jiffies; } else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 3)) acc = accel[0]; else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 2)) acc = accel[1]; else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 1)) acc = accel[2]; else if ((jiffies - ati_remote->acc_jiffies) < HZ ) acc = accel[3]; else if ((jiffies - ati_remote->acc_jiffies) < HZ+(HZ>>1)) acc = accel[4]; else if ((jiffies - ati_remote->acc_jiffies) < (HZ << 1)) acc = accel[5]; else acc = accel[6]; input_regs(dev, regs); switch (ati_remote_tbl[index].kind) { case KIND_ACCEL: input_event(dev, ati_remote_tbl[index].type, ati_remote_tbl[index].code, ati_remote_tbl[index].value * acc); break; case KIND_LU: input_report_rel(dev, REL_X, -acc); input_report_rel(dev, REL_Y, -acc); break; case KIND_RU: input_report_rel(dev, REL_X, acc); input_report_rel(dev, REL_Y, -acc); break; case KIND_LD: input_report_rel(dev, REL_X, -acc); input_report_rel(dev, REL_Y, acc); break; case KIND_RD: input_report_rel(dev, REL_X, acc); input_report_rel(dev, REL_Y, acc); break; default: dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", ati_remote_tbl[index].kind); } input_sync(dev); ati_remote->old_jiffies = jiffies; ati_remote->old_data[0] = data[1]; ati_remote->old_data[1] = data[2];}/* * ati_remote_irq_in */static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs){ struct ati_remote *ati_remote = urb->context; int retval; switch (urb->status) { case 0: /* success */ ati_remote_input_report(urb, regs); break; case -ECONNRESET: /* unlink */ case -ENOENT: case -ESHUTDOWN: dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n", __FUNCTION__); return; default: /* error */ dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", __FUNCTION__, urb->status); } retval = usb_submit_urb(urb, SLAB_ATOMIC); if (retval) dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", __FUNCTION__, retval);}/* * ati_remote_alloc_buffers */static int ati_remote_alloc_buffers(struct usb_device *udev, struct ati_remote *ati_remote){ ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC, &ati_remote->inbuf_dma); if (!ati_remote->inbuf) return -1; ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC, &ati_remote->outbuf_dma); if (!ati_remote->outbuf) return -1; ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); if (!ati_remote->irq_urb) return -1; ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL); if (!ati_remote->out_urb) return -1; return 0;}/* * ati_remote_free_buffers */static void ati_remote_free_buffers(struct ati_remote *ati_remote){ if (ati_remote->irq_urb) usb_free_urb(ati_remote->irq_urb); if (ati_remote->out_urb) usb_free_urb(ati_remote->out_urb); if (ati_remote->inbuf) usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, ati_remote->inbuf, ati_remote->inbuf_dma); if (ati_remote->outbuf) usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, ati_remote->inbuf, ati_remote->outbuf_dma);}static void ati_remote_input_init(struct ati_remote *ati_remote){ struct input_dev *idev = ati_remote->idev; int i; idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_SIDE) | BIT(BTN_EXTRA) ); idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) if (ati_remote_tbl[i].type == EV_KEY) set_bit(ati_remote_tbl[i].code, idev->keybit); idev->private = ati_remote; idev->open = ati_remote_open; idev->close = ati_remote_close; idev->name = ati_remote->name; idev->phys = ati_remote->phys; usb_to_input_id(ati_remote->udev, &idev->id); idev->cdev.dev = &ati_remote->udev->dev;}static int ati_remote_initialize(struct ati_remote *ati_remote){ struct usb_device *udev = ati_remote->udev; int pipe, maxp; init_waitqueue_head(&ati_remote->wait); /* Set up irq_urb */ pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, maxp, ati_remote_irq_in, ati_remote, ati_remote->endpoint_in->bInterval); ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* Set up out_urb */ pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, maxp, ati_remote_irq_out, ati_remote, ati_remote->endpoint_out->bInterval); ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* send initialization strings */ if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { dev_err(&ati_remote->interface->dev, "Initializing ati_remote hardware failed.\n"); return -EIO; } return 0;}/* * ati_remote_probe */static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id){ struct usb_device *udev = interface_to_usbdev(interface); struct usb_host_interface *iface_host = interface->cur_altsetting; struct usb_endpoint_descriptor *endpoint_in, *endpoint_out; struct ati_remote *ati_remote; struct input_dev *input_dev; int err = -ENOMEM; if (iface_host->desc.bNumEndpoints != 2) { err("%s: Unexpected desc.bNumEndpoints\n", __FUNCTION__); return -ENODEV; } endpoint_in = &iface_host->endpoint[0].desc; endpoint_out = &iface_host->endpoint[1].desc; if (!(endpoint_in->bEndpointAddress & USB_DIR_IN)) { err("%s: Unexpected endpoint_in->bEndpointAddress\n", __FUNCTION__); return -ENODEV; } if ((endpoint_in->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) { err("%s: Unexpected endpoint_in->bmAttributes\n", __FUNCTION__); return -ENODEV; } if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) { err("%s: endpoint_in message size==0? \n", __FUNCTION__); return -ENODEV; } ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL); input_dev = input_allocate_device(); if (!ati_remote || !input_dev) goto fail1; /* Allocate URB buffers, URBs */ if (ati_remote_alloc_buffers(udev, ati_remote)) goto fail2; ati_remote->endpoint_in = endpoint_in; ati_remote->endpoint_out = endpoint_out; ati_remote->udev = udev; ati_remote->idev = input_dev; ati_remote->interface = interface; usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys)); strlcpy(ati_remote->phys, "/input0", sizeof(ati_remote->phys)); if (udev->manufacturer) strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name)); if (udev->product) snprintf(ati_remote->name, sizeof(ati_remote->name), "%s %s", ati_remote->name, udev->product); if (!strlen(ati_remote->name)) snprintf(ati_remote->name, sizeof(ati_remote->name), DRIVER_DESC "(%04x,%04x)", le16_to_cpu(ati_remote->udev->descriptor.idVendor), le16_to_cpu(ati_remote->udev->descriptor.idProduct)); ati_remote_input_init(ati_remote); /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ err = ati_remote_initialize(ati_remote); if (err) goto fail3; /* Set up and register input device */ input_register_device(ati_remote->idev); usb_set_intfdata(interface, ati_remote); return 0;fail3: usb_kill_urb(ati_remote->irq_urb); usb_kill_urb(ati_remote->out_urb);fail2: ati_remote_free_buffers(ati_remote);fail1: input_free_device(input_dev); kfree(ati_remote); return err;}/* * ati_remote_disconnect */static void ati_remote_disconnect(struct usb_interface *interface){ struct ati_remote *ati_remote; ati_remote = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); if (!ati_remote) { warn("%s - null device?\n", __FUNCTION__); return; } usb_kill_urb(ati_remote->irq_urb); usb_kill_urb(ati_remote->out_urb); input_unregister_device(ati_remote->idev); ati_remote_free_buffers(ati_remote); kfree(ati_remote);}/* * ati_remote_init */static int __init ati_remote_init(void){ int result; result = usb_register(&ati_remote_driver); if (result) err("usb_register error #%d\n", result); else info("Registered USB driver " DRIVER_DESC " v. " DRIVER_VERSION); return result;}/* * ati_remote_exit */static void __exit ati_remote_exit(void){ usb_deregister(&ati_remote_driver);}/* * module specification */module_init(ati_remote_init);module_exit(ati_remote_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -