@@ -138,6 +138,7 @@
struct module *module; /* subdriver handling the device */
struct usb_device *dev;
struct file *capt_file; /* file doing video capture */
+ struct input_dev *input_dev;
struct cam cam; /* device information */
const struct sd_desc *sd_desc; /* subdriver description */
@@ -147,6 +148,7 @@
#define USB_BUF_SZ 64
__u8 *usb_buf; /* buffer for USB exchanges */
struct urb *urb[MAX_NURBS];
+ struct urb *int_urb;
__u8 *frbuf; /* buffer for nframes */
struct gspca_frame frame[GSPCA_MAX_FRAMES];
@@ -68,6 +68,7 @@
#define MODULE_NAME "pac7302"
+#include <linux/input.h>
#include <media/v4l2-chip-ident.h>
#include "gspca.h"
@@ -1220,6 +1221,50 @@
}
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void int_irq(struct urb *urb, struct pt_regs *regs)
+#else
+static void int_irq(struct urb *urb)
+#endif
+{
+ struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
+ int ret;
+ int i;
+ __u8 data0, data1;
+
+ printk(KERN_DEBUG "int_irq()\n");
+ printk(KERN_DEBUG "urb->status: %i\n", urb->status);
+ if (urb->status == 0) {
+ printk(KERN_DEBUG "urb->actual_length: %u\n", urb->actual_length);
+ for (i = 0; i < urb->actual_length; i++) {
+ printk(KERN_DEBUG "urb->transfer_buffer[%i]=0x%x\n",
+ i, ((__u8*)urb->transfer_buffer)[i]);
+ }
+ if (urb->actual_length == 2) {
+ data0 = ((__u8*)urb->transfer_buffer)[0];
+ data1 = ((__u8*)urb->transfer_buffer)[1];
+ if ((data0 == 0x00 && data1 == 0x11) ||
+ (data0 == 0x22 && data1 == 0x33) ||
+ (data0 == 0x44 && data1 == 0x55) ||
+ (data0 == 0x66 && data1 == 0x77) ||
+ (data0 == 0x88 && data1 == 0x99) ||
+ (data0 == 0xaa && data1 == 0xbb) ||
+ (data0 == 0xcc && data1 == 0xdd) ||
+ (data0 == 0xee && data1 == 0xff)) {
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
+ input_sync(gspca_dev->input_dev);
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+ input_sync(gspca_dev->input_dev);
+ } else
+ printk(KERN_DEBUG "Unknown packet received\n");
+ }
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ printk(KERN_DEBUG "resubmit urb: %i\n", ret);
+ }
+
+}
+
+
/* sub-driver description for pac7302 */
static struct sd_desc sd_desc = {
.name = MODULE_NAME,
@@ -1254,19 +1299,132 @@
};
MODULE_DEVICE_TABLE(usb, device_table);
+static int init_camera_input(struct gspca_dev *gspca_dev, const struct usb_device_id *id)
+{
+ struct input_dev *input_dev;
+ int err;
+
+ printk(KERN_DEBUG "allocating input device\n");
+ input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
+
+ //input_dev->name = "Camera capture button";
+ //input_dev->phys = "camera";
+ input_dev->id.bustype = BUS_USB;
+ input_dev->id.vendor = id->idVendor;
+ input_dev->id.product = id->idProduct;
+ input_dev->id.version = id->bcdDevice_hi;
+ //input_dev->id.version = id->bcdDevice_lo;
+
+ input_dev->evbit[0] = BIT_MASK(EV_KEY);
+ input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
+ //input_dev->dev.parent = ;
+
+ printk(KERN_DEBUG "registering input device\n");
+ err = input_register_device(input_dev);
+ if (err) {
+ input_dev->dev.parent = NULL;
+ input_free_device(input_dev);
+ } else {
+ gspca_dev->input_dev = input_dev;
+ }
+
+ return err;
+}
+
/* -- device connect -- */
static int sd_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
+ int ret;
+ struct usb_host_interface *intf_desc;
+ struct usb_endpoint_descriptor *ep;
+ int i;
+
+ struct urb *urb;
+ void* buffer = NULL;
+ unsigned int buffer_len;
+ int interval;
+ struct gspca_dev *gspca_dev;
+ struct usb_device *dev;
+
+ ret = gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
THIS_MODULE);
+ if (0 <= ret) {
+ intf_desc = intf->cur_altsetting;
+ for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
+ ep = &intf_desc->endpoint[i].desc;
+ if ((ep->bEndpointAddress & USB_DIR_IN) &&
+ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_INT)) {
+
+ buffer_len = ep->wMaxPacketSize;
+ interval = ep->bInterval;
+ printk(KERN_DEBUG "found int in endpoint: 0x%x\n", ep->bEndpointAddress);
+ printk(KERN_DEBUG " - buffer_len = %u\n", buffer_len);
+ printk(KERN_DEBUG " - interval = %u\n", interval);
+
+ gspca_dev = usb_get_intfdata(intf);
+ dev = gspca_dev->dev;
+ gspca_dev->int_urb = NULL;
+ gspca_dev->input_dev = NULL;
+
+ buffer = kmalloc(ep->wMaxPacketSize, GFP_KERNEL);
+ if (buffer)
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ else {
+ kfree(buffer);
+ urb = NULL;
+ }
+ if (buffer && urb) {
+ usb_fill_int_urb(urb, dev,
+ usb_rcvintpipe(dev, ep->bEndpointAddress),
+ buffer, buffer_len,
+ int_irq, (void*)gspca_dev, interval);
+ ret = init_camera_input(gspca_dev, id);
+ if (0 <= ret) {
+ gspca_dev->int_urb = urb;
+ ret = usb_submit_urb(urb, GFP_KERNEL);
+ printk(KERN_DEBUG "usb_submit_urb() returns %i\n", ret);
+ }
+ }
+ }
+
+ }
+ }
+ return ret;
+}
+
+static void sd_disconnect(struct usb_interface *intf)
+{
+ struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+ struct urb *urb;
+ struct input_dev *input_dev;
+
+ urb = gspca_dev->int_urb;
+ if (urb != NULL) {
+ gspca_dev->int_urb = NULL;
+ usb_kill_urb(urb);
+ usb_buffer_free(gspca_dev->dev,
+ urb->transfer_buffer_length,
+ urb->transfer_buffer,
+ urb->transfer_dma);
+ usb_free_urb(urb);
+ }
+ input_dev = gspca_dev->input_dev;
+ if (input_dev) {
+ gspca_dev->input_dev = NULL;
+ input_unregister_device(input_dev);
+ }
+ gspca_disconnect(intf);
}
static struct usb_driver sd_driver = {
.name = MODULE_NAME,
.id_table = device_table,
.probe = sd_probe,
- .disconnect = gspca_disconnect,
+ .disconnect = sd_disconnect,
#ifdef CONFIG_PM
.suspend = gspca_suspend,
.resume = gspca_resume,