aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMárton Németh <nm127@freemail.hu>2010-01-28 04:39:49 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-02-26 13:10:49 -0500
commit0274d42e052ecd9bc6b5f69fbfc8792ce2cc0fb6 (patch)
treec16f3c1d5f17956ce82b425473e13f5a27cfb240
parent2abf6dd8e8754db6b18a4d55d3e4425c0a22d280 (diff)
V4L/DVB: gspca - main: Add input support for interrupt endpoints.
Signed-off-by: Márton Németh <nm127@freemail.hu> Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/gspca/gspca.c203
-rw-r--r--drivers/media/video/gspca/gspca.h13
2 files changed, 215 insertions, 1 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 6a6e22c61779..c70d33bf6aad 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -3,6 +3,9 @@
3 * 3 *
4 * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr) 4 * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr)
5 * 5 *
6 * Camera button input handling by Márton Németh
7 * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
8 *
6 * This program is free software; you can redistribute it and/or modify it 9 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 10 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your 11 * Free Software Foundation; either version 2 of the License, or (at your
@@ -37,6 +40,9 @@
37 40
38#include "gspca.h" 41#include "gspca.h"
39 42
43#include <linux/input.h>
44#include <linux/usb/input.h>
45
40/* global values */ 46/* global values */
41#define DEF_NURBS 3 /* default number of URBs */ 47#define DEF_NURBS 3 /* default number of URBs */
42#if DEF_NURBS > MAX_NURBS 48#if DEF_NURBS > MAX_NURBS
@@ -104,6 +110,182 @@ static const struct vm_operations_struct gspca_vm_ops = {
104 .close = gspca_vm_close, 110 .close = gspca_vm_close,
105}; 111};
106 112
113/*
114 * Input and interrupt endpoint handling functions
115 */
116#ifdef CONFIG_INPUT
117static void int_irq(struct urb *urb)
118{
119 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
120 int ret;
121
122 ret = urb->status;
123 switch (ret) {
124 case 0:
125 if (gspca_dev->sd_desc->int_pkt_scan(gspca_dev,
126 urb->transfer_buffer, urb->actual_length) < 0) {
127 PDEBUG(D_ERR, "Unknown packet received");
128 }
129 break;
130
131 case -ENOENT:
132 case -ECONNRESET:
133 case -ENODEV:
134 case -ESHUTDOWN:
135 /* Stop is requested either by software or hardware is gone,
136 * keep the ret value non-zero and don't resubmit later.
137 */
138 break;
139
140 default:
141 PDEBUG(D_ERR, "URB error %i, resubmitting", urb->status);
142 urb->status = 0;
143 ret = 0;
144 }
145
146 if (ret == 0) {
147 ret = usb_submit_urb(urb, GFP_ATOMIC);
148 if (ret < 0)
149 PDEBUG(D_ERR, "Resubmit URB failed with error %i", ret);
150 }
151}
152
153static int gspca_input_connect(struct gspca_dev *dev)
154{
155 struct input_dev *input_dev;
156 int err = 0;
157
158 dev->input_dev = NULL;
159 if (dev->sd_desc->int_pkt_scan) {
160 input_dev = input_allocate_device();
161 if (!input_dev)
162 return -ENOMEM;
163
164 usb_make_path(dev->dev, dev->phys, sizeof(dev->phys));
165 strlcat(dev->phys, "/input0", sizeof(dev->phys));
166
167 input_dev->name = dev->sd_desc->name;
168 input_dev->phys = dev->phys;
169
170 usb_to_input_id(dev->dev, &input_dev->id);
171
172 input_dev->evbit[0] = BIT_MASK(EV_KEY);
173 input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
174 input_dev->dev.parent = &dev->dev->dev;
175
176 err = input_register_device(input_dev);
177 if (err) {
178 PDEBUG(D_ERR, "Input device registration failed "
179 "with error %i", err);
180 input_dev->dev.parent = NULL;
181 input_free_device(input_dev);
182 } else {
183 dev->input_dev = input_dev;
184 }
185 } else
186 err = -EINVAL;
187
188 return err;
189}
190
191static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
192 struct usb_endpoint_descriptor *ep)
193{
194 unsigned int buffer_len;
195 int interval;
196 struct urb *urb;
197 struct usb_device *dev;
198 void *buffer = NULL;
199 int ret = -EINVAL;
200
201 buffer_len = ep->wMaxPacketSize;
202 interval = ep->bInterval;
203 PDEBUG(D_PROBE, "found int in endpoint: 0x%x, "
204 "buffer_len=%u, interval=%u",
205 ep->bEndpointAddress, buffer_len, interval);
206
207 dev = gspca_dev->dev;
208
209 urb = usb_alloc_urb(0, GFP_KERNEL);
210 if (!urb) {
211 ret = -ENOMEM;
212 goto error;
213 }
214
215 buffer = usb_buffer_alloc(dev, ep->wMaxPacketSize,
216 GFP_KERNEL, &urb->transfer_dma);
217 if (!buffer) {
218 ret = -ENOMEM;
219 goto error_buffer;
220 }
221 usb_fill_int_urb(urb, dev,
222 usb_rcvintpipe(dev, ep->bEndpointAddress),
223 buffer, buffer_len,
224 int_irq, (void *)gspca_dev, interval);
225 gspca_dev->int_urb = urb;
226 ret = usb_submit_urb(urb, GFP_KERNEL);
227 if (ret < 0) {
228 PDEBUG(D_ERR, "submit URB failed with error %i", ret);
229 goto error_submit;
230 }
231 return ret;
232
233error_submit:
234 usb_buffer_free(dev,
235 urb->transfer_buffer_length,
236 urb->transfer_buffer,
237 urb->transfer_dma);
238error_buffer:
239 usb_free_urb(urb);
240error:
241 return ret;
242}
243
244static int gspca_input_create_urb(struct gspca_dev *gspca_dev)
245{
246 int ret = -EINVAL;
247 struct usb_interface *intf;
248 struct usb_host_interface *intf_desc;
249 struct usb_endpoint_descriptor *ep;
250 int i;
251
252 if (gspca_dev->sd_desc->int_pkt_scan) {
253 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
254 intf_desc = intf->cur_altsetting;
255 for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
256 ep = &intf_desc->endpoint[i].desc;
257 if (usb_endpoint_dir_in(ep) &&
258 usb_endpoint_xfer_int(ep)) {
259
260 ret = alloc_and_submit_int_urb(gspca_dev, ep);
261 break;
262 }
263 }
264 }
265 return ret;
266}
267
268static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev)
269{
270 struct urb *urb;
271
272 urb = gspca_dev->int_urb;
273 if (urb) {
274 gspca_dev->int_urb = NULL;
275 usb_kill_urb(urb);
276 usb_buffer_free(gspca_dev->dev,
277 urb->transfer_buffer_length,
278 urb->transfer_buffer,
279 urb->transfer_dma);
280 usb_free_urb(urb);
281 }
282}
283#else
284#define gspca_input_connect(gspca_dev) 0
285#define gspca_input_create_urb(gspca_dev) 0
286#define gspca_input_destroy_urb(gspca_dev)
287#endif
288
107/* get the current input frame buffer */ 289/* get the current input frame buffer */
108struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev) 290struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev)
109{ 291{
@@ -483,11 +665,13 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev)
483 i, ep->desc.bEndpointAddress); 665 i, ep->desc.bEndpointAddress);
484 gspca_dev->alt = i; /* memorize the current alt setting */ 666 gspca_dev->alt = i; /* memorize the current alt setting */
485 if (gspca_dev->nbalt > 1) { 667 if (gspca_dev->nbalt > 1) {
668 gspca_input_destroy_urb(gspca_dev);
486 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); 669 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
487 if (ret < 0) { 670 if (ret < 0) {
488 err("set alt %d err %d", i, ret); 671 err("set alt %d err %d", i, ret);
489 return NULL; 672 ep = NULL;
490 } 673 }
674 gspca_input_create_urb(gspca_dev);
491 } 675 }
492 return ep; 676 return ep;
493} 677}
@@ -698,7 +882,9 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
698 if (gspca_dev->sd_desc->stopN) 882 if (gspca_dev->sd_desc->stopN)
699 gspca_dev->sd_desc->stopN(gspca_dev); 883 gspca_dev->sd_desc->stopN(gspca_dev);
700 destroy_urbs(gspca_dev); 884 destroy_urbs(gspca_dev);
885 gspca_input_destroy_urb(gspca_dev);
701 gspca_set_alt0(gspca_dev); 886 gspca_set_alt0(gspca_dev);
887 gspca_input_create_urb(gspca_dev);
702 } 888 }
703 889
704 /* always call stop0 to free the subdriver's resources */ 890 /* always call stop0 to free the subdriver's resources */
@@ -2121,6 +2307,11 @@ int gspca_dev_probe(struct usb_interface *intf,
2121 2307
2122 usb_set_intfdata(intf, gspca_dev); 2308 usb_set_intfdata(intf, gspca_dev);
2123 PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev)); 2309 PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev));
2310
2311 ret = gspca_input_connect(gspca_dev);
2312 if (ret == 0)
2313 ret = gspca_input_create_urb(gspca_dev);
2314
2124 return 0; 2315 return 0;
2125out: 2316out:
2126 kfree(gspca_dev->usb_buf); 2317 kfree(gspca_dev->usb_buf);
@@ -2138,6 +2329,7 @@ EXPORT_SYMBOL(gspca_dev_probe);
2138void gspca_disconnect(struct usb_interface *intf) 2329void gspca_disconnect(struct usb_interface *intf)
2139{ 2330{
2140 struct gspca_dev *gspca_dev = usb_get_intfdata(intf); 2331 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
2332 struct input_dev *input_dev;
2141 2333
2142 PDEBUG(D_PROBE, "%s disconnect", 2334 PDEBUG(D_PROBE, "%s disconnect",
2143 video_device_node_name(&gspca_dev->vdev)); 2335 video_device_node_name(&gspca_dev->vdev));
@@ -2149,6 +2341,13 @@ void gspca_disconnect(struct usb_interface *intf)
2149 wake_up_interruptible(&gspca_dev->wq); 2341 wake_up_interruptible(&gspca_dev->wq);
2150 } 2342 }
2151 2343
2344 gspca_input_destroy_urb(gspca_dev);
2345 input_dev = gspca_dev->input_dev;
2346 if (input_dev) {
2347 gspca_dev->input_dev = NULL;
2348 input_unregister_device(input_dev);
2349 }
2350
2152 /* the device is freed at exit of this function */ 2351 /* the device is freed at exit of this function */
2153 gspca_dev->dev = NULL; 2352 gspca_dev->dev = NULL;
2154 mutex_unlock(&gspca_dev->usb_lock); 2353 mutex_unlock(&gspca_dev->usb_lock);
@@ -2174,6 +2373,7 @@ int gspca_suspend(struct usb_interface *intf, pm_message_t message)
2174 if (gspca_dev->sd_desc->stopN) 2373 if (gspca_dev->sd_desc->stopN)
2175 gspca_dev->sd_desc->stopN(gspca_dev); 2374 gspca_dev->sd_desc->stopN(gspca_dev);
2176 destroy_urbs(gspca_dev); 2375 destroy_urbs(gspca_dev);
2376 gspca_input_destroy_urb(gspca_dev);
2177 gspca_set_alt0(gspca_dev); 2377 gspca_set_alt0(gspca_dev);
2178 if (gspca_dev->sd_desc->stop0) 2378 if (gspca_dev->sd_desc->stop0)
2179 gspca_dev->sd_desc->stop0(gspca_dev); 2379 gspca_dev->sd_desc->stop0(gspca_dev);
@@ -2187,6 +2387,7 @@ int gspca_resume(struct usb_interface *intf)
2187 2387
2188 gspca_dev->frozen = 0; 2388 gspca_dev->frozen = 0;
2189 gspca_dev->sd_desc->init(gspca_dev); 2389 gspca_dev->sd_desc->init(gspca_dev);
2390 gspca_input_create_urb(gspca_dev);
2190 if (gspca_dev->streaming) 2391 if (gspca_dev->streaming)
2191 return gspca_init_transfer(gspca_dev); 2392 return gspca_init_transfer(gspca_dev);
2192 return 0; 2393 return 0;
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index 53c034ea84ad..0ed254b496a5 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -91,6 +91,9 @@ typedef int (*cam_qmnu_op) (struct gspca_dev *,
91typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev, 91typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev,
92 u8 *data, 92 u8 *data,
93 int len); 93 int len);
94typedef int (*cam_int_pkt_op) (struct gspca_dev *gspca_dev,
95 u8 *data,
96 int len);
94 97
95struct ctrl { 98struct ctrl {
96 struct v4l2_queryctrl qctrl; 99 struct v4l2_queryctrl qctrl;
@@ -126,6 +129,9 @@ struct sd_desc {
126 cam_reg_op get_register; 129 cam_reg_op get_register;
127#endif 130#endif
128 cam_ident_op get_chip_ident; 131 cam_ident_op get_chip_ident;
132#ifdef CONFIG_INPUT
133 cam_int_pkt_op int_pkt_scan;
134#endif
129}; 135};
130 136
131/* packet types when moving from iso buf to frame buf */ 137/* packet types when moving from iso buf to frame buf */
@@ -148,6 +154,10 @@ struct gspca_dev {
148 struct module *module; /* subdriver handling the device */ 154 struct module *module; /* subdriver handling the device */
149 struct usb_device *dev; 155 struct usb_device *dev;
150 struct file *capt_file; /* file doing video capture */ 156 struct file *capt_file; /* file doing video capture */
157#ifdef CONFIG_INPUT
158 struct input_dev *input_dev;
159 char phys[64]; /* physical device path */
160#endif
151 161
152 struct cam cam; /* device information */ 162 struct cam cam; /* device information */
153 const struct sd_desc *sd_desc; /* subdriver description */ 163 const struct sd_desc *sd_desc; /* subdriver description */
@@ -157,6 +167,9 @@ struct gspca_dev {
157#define USB_BUF_SZ 64 167#define USB_BUF_SZ 64
158 __u8 *usb_buf; /* buffer for USB exchanges */ 168 __u8 *usb_buf; /* buffer for USB exchanges */
159 struct urb *urb[MAX_NURBS]; 169 struct urb *urb[MAX_NURBS];
170#ifdef CONFIG_INPUT
171 struct urb *int_urb;
172#endif
160 173
161 __u8 *frbuf; /* buffer for nframes */ 174 __u8 *frbuf; /* buffer for nframes */
162 struct gspca_frame frame[GSPCA_MAX_FRAMES]; 175 struct gspca_frame frame[GSPCA_MAX_FRAMES];