aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/video/gspca/finepix.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/finepix.c')
-rw-r--r--drivers/media/video/gspca/finepix.c471
1 files changed, 0 insertions, 471 deletions
diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c
deleted file mode 100644
index afc8b2dd307..00000000000
--- a/drivers/media/video/gspca/finepix.c
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * Fujifilm Finepix subdriver
- *
- * Copyright (C) 2008 Frank Zago
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define MODULE_NAME "finepix"
-
-#include "gspca.h"
-
-MODULE_AUTHOR("Frank Zago <frank@zago.net>");
-MODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver");
-MODULE_LICENSE("GPL");
-
-/* Default timeout, in ms */
-#define FPIX_TIMEOUT (HZ / 10)
-
-/* Maximum transfer size to use. The windows driver reads by chunks of
- * 0x2000 bytes, so do the same. Note: reading more seems to work
- * too. */
-#define FPIX_MAX_TRANSFER 0x2000
-
-/* Structure to hold all of our device specific stuff */
-struct usb_fpix {
- struct gspca_dev gspca_dev; /* !! must be the first item */
-
- /*
- * USB stuff
- */
- struct usb_ctrlrequest ctrlreq;
- struct urb *control_urb;
- struct timer_list bulk_timer;
-
- enum {
- FPIX_NOP, /* inactive, else streaming */
- FPIX_RESET, /* must reset */
- FPIX_REQ_FRAME, /* requesting a frame */
- FPIX_READ_FRAME, /* reading frame */
- } state;
-
- /*
- * Driver stuff
- */
- struct delayed_work wqe;
- struct completion can_close;
- int streaming;
-};
-
-/* Delay after which claim the next frame. If the delay is too small,
- * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms
- * will fail every 4 or 5 frames, but 30ms is perfect. */
-#define NEXT_FRAME_DELAY (((HZ * 30) + 999) / 1000)
-
-#define dev_new_state(new_state) { \
- PDEBUG(D_STREAM, "new state from %d to %d at %s:%d", \
- dev->state, new_state, __func__, __LINE__); \
- dev->state = new_state; \
-}
-
-/* These cameras only support 320x200. */
-static const struct v4l2_pix_format fpix_mode[1] = {
- { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
- .bytesperline = 320,
- .sizeimage = 320 * 240 * 3 / 8 + 590,
- .colorspace = V4L2_COLORSPACE_SRGB,
- .priv = 0}
-};
-
-/* Reads part of a frame */
-static void read_frame_part(struct usb_fpix *dev)
-{
- int ret;
-
- PDEBUG(D_STREAM, "read_frame_part");
-
- /* Reads part of a frame */
- ret = usb_submit_urb(dev->gspca_dev.urb[0], GFP_ATOMIC);
- if (ret) {
- dev_new_state(FPIX_RESET);
- schedule_delayed_work(&dev->wqe, 1);
- PDEBUG(D_STREAM, "usb_submit_urb failed with %d",
- ret);
- } else {
- /* Sometimes we never get a callback, so use a timer.
- * Is this masking a bug somewhere else? */
- dev->bulk_timer.expires = jiffies + msecs_to_jiffies(150);
- add_timer(&dev->bulk_timer);
- }
-}
-
-/* Callback for URBs. */
-static void urb_callback(struct urb *urb)
-{
- struct gspca_dev *gspca_dev = urb->context;
- struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
-
- PDEBUG(D_PACK,
- "enter urb_callback - status=%d, length=%d",
- urb->status, urb->actual_length);
-
- if (dev->state == FPIX_READ_FRAME)
- del_timer(&dev->bulk_timer);
-
- if (urb->status != 0) {
- /* We kill a stuck urb every 50 frames on average, so don't
- * display a log message for that. */
- if (urb->status != -ECONNRESET)
- PDEBUG(D_STREAM, "bad URB status %d", urb->status);
- dev_new_state(FPIX_RESET);
- schedule_delayed_work(&dev->wqe, 1);
- }
-
- switch (dev->state) {
- case FPIX_REQ_FRAME:
- dev_new_state(FPIX_READ_FRAME);
- read_frame_part(dev);
- break;
-
- case FPIX_READ_FRAME: {
- unsigned char *data = urb->transfer_buffer;
- struct gspca_frame *frame;
-
- frame = gspca_get_i_frame(&dev->gspca_dev);
- if (frame == NULL)
- gspca_dev->last_packet_type = DISCARD_PACKET;
- if (urb->actual_length < FPIX_MAX_TRANSFER ||
- (data[urb->actual_length-2] == 0xff &&
- data[urb->actual_length-1] == 0xd9)) {
-
- /* If the result is less than what was asked
- * for, then it's the end of the
- * frame. Sometime the jpeg is not complete,
- * but there's nothing we can do. We also end
- * here if the the jpeg ends right at the end
- * of the frame. */
- if (frame)
- gspca_frame_add(gspca_dev, LAST_PACKET,
- frame,
- data, urb->actual_length);
- dev_new_state(FPIX_REQ_FRAME);
- schedule_delayed_work(&dev->wqe, NEXT_FRAME_DELAY);
- } else {
-
- /* got a partial image */
- if (frame)
- gspca_frame_add(gspca_dev,
- gspca_dev->last_packet_type
- == LAST_PACKET
- ? FIRST_PACKET : INTER_PACKET,
- frame,
- data, urb->actual_length);
- read_frame_part(dev);
- }
- break;
- }
-
- case FPIX_NOP:
- case FPIX_RESET:
- PDEBUG(D_STREAM, "invalid state %d", dev->state);
- break;
- }
-}
-
-/* Request a new frame */
-static void request_frame(struct usb_fpix *dev)
-{
- int ret;
- struct gspca_dev *gspca_dev = &dev->gspca_dev;
-
- /* Setup command packet */
- memset(gspca_dev->usb_buf, 0, 12);
- gspca_dev->usb_buf[0] = 0xd3;
- gspca_dev->usb_buf[7] = 0x01;
-
- /* Request a frame */
- dev->ctrlreq.bRequestType =
- USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
- dev->ctrlreq.bRequest = USB_REQ_GET_STATUS;
- dev->ctrlreq.wValue = 0;
- dev->ctrlreq.wIndex = 0;
- dev->ctrlreq.wLength = cpu_to_le16(12);
-
- usb_fill_control_urb(dev->control_urb,
- gspca_dev->dev,
- usb_sndctrlpipe(gspca_dev->dev, 0),
- (unsigned char *) &dev->ctrlreq,
- gspca_dev->usb_buf,
- 12, urb_callback, gspca_dev);
-
- ret = usb_submit_urb(dev->control_urb, GFP_ATOMIC);
- if (ret) {
- dev_new_state(FPIX_RESET);
- schedule_delayed_work(&dev->wqe, 1);
- PDEBUG(D_STREAM, "usb_submit_urb failed with %d", ret);
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-/* State machine. */
-static void fpix_sm(struct work_struct *work)
-{
- struct usb_fpix *dev = container_of(work, struct usb_fpix, wqe.work);
-
- PDEBUG(D_STREAM, "fpix_sm state %d", dev->state);
-
- /* verify that the device wasn't unplugged */
- if (!dev->gspca_dev.present) {
- PDEBUG(D_STREAM, "device is gone");
- dev_new_state(FPIX_NOP);
- complete(&dev->can_close);
- return;
- }
-
- if (!dev->streaming) {
- PDEBUG(D_STREAM, "stopping state machine");
- dev_new_state(FPIX_NOP);
- complete(&dev->can_close);
- return;
- }
-
- switch (dev->state) {
- case FPIX_RESET:
- dev_new_state(FPIX_REQ_FRAME);
- schedule_delayed_work(&dev->wqe, HZ / 10);
- break;
-
- case FPIX_REQ_FRAME:
- /* get an image */
- request_frame(dev);
- break;
-
- case FPIX_NOP:
- case FPIX_READ_FRAME:
- PDEBUG(D_STREAM, "invalid state %d", dev->state);
- break;
- }
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
- const struct usb_device_id *id)
-{
- struct cam *cam = &gspca_dev->cam;
-
- cam->cam_mode = fpix_mode;
- cam->nmodes = 1;
- cam->epaddr = 0x01; /* todo: correct for all cams? */
- cam->bulk_size = FPIX_MAX_TRANSFER;
-
-/* gspca_dev->nbalt = 1; * use bulk transfer */
- return 0;
-}
-
-/* Stop streaming and free the ressources allocated by sd_start. */
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
- struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
-
- dev->streaming = 0;
-
- /* Stop the state machine */
- if (dev->state != FPIX_NOP)
- wait_for_completion(&dev->can_close);
-}
-
-/* called on streamoff with alt 0 and disconnect */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
- struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
-
- usb_free_urb(dev->control_urb);
- dev->control_urb = NULL;
-}
-
-/* Kill an URB that hasn't completed. */
-static void timeout_kill(unsigned long data)
-{
- struct urb *urb = (struct urb *) data;
-
- usb_unlink_urb(urb);
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
- struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
-
- INIT_DELAYED_WORK(&dev->wqe, fpix_sm);
-
- init_timer(&dev->bulk_timer);
- dev->bulk_timer.function = timeout_kill;
-
- return 0;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
- struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
- int ret;
- int size_ret;
-
- /* Init the device */
- memset(gspca_dev->usb_buf, 0, 12);
- gspca_dev->usb_buf[0] = 0xc6;
- gspca_dev->usb_buf[8] = 0x20;
-
- ret = usb_control_msg(gspca_dev->dev,
- usb_sndctrlpipe(gspca_dev->dev, 0),
- USB_REQ_GET_STATUS,
- USB_DIR_OUT | USB_TYPE_CLASS |
- USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
- 12, FPIX_TIMEOUT);
-
- if (ret != 12) {
- PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret);
- ret = -EIO;
- goto error;
- }
-
- /* Read the result of the command. Ignore the result, for it
- * varies with the device. */
- ret = usb_bulk_msg(gspca_dev->dev,
- usb_rcvbulkpipe(gspca_dev->dev,
- gspca_dev->cam.epaddr),
- gspca_dev->usb_buf, FPIX_MAX_TRANSFER, &size_ret,
- FPIX_TIMEOUT);
- if (ret != 0) {
- PDEBUG(D_STREAM, "usb_bulk_msg failed (%d)", ret);
- ret = -EIO;
- goto error;
- }
-
- /* Request a frame, but don't read it */
- memset(gspca_dev->usb_buf, 0, 12);
- gspca_dev->usb_buf[0] = 0xd3;
- gspca_dev->usb_buf[7] = 0x01;
-
- ret = usb_control_msg(gspca_dev->dev,
- usb_sndctrlpipe(gspca_dev->dev, 0),
- USB_REQ_GET_STATUS,
- USB_DIR_OUT | USB_TYPE_CLASS |
- USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
- 12, FPIX_TIMEOUT);
- if (ret != 12) {
- PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret);
- ret = -EIO;
- goto error;
- }
-
- /* Again, reset bulk in endpoint */
- usb_clear_halt(gspca_dev->dev, gspca_dev->cam.epaddr);
-
- /* Allocate a control URB */
- dev->control_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!dev->control_urb) {
- PDEBUG(D_STREAM, "No free urbs available");
- ret = -EIO;
- goto error;
- }
-
- /* Various initializations. */
- init_completion(&dev->can_close);
- dev->bulk_timer.data = (unsigned long)dev->gspca_dev.urb[0];
- dev->gspca_dev.urb[0]->complete = urb_callback;
- dev->streaming = 1;
-
- /* Schedule a frame request. */
- dev_new_state(FPIX_REQ_FRAME);
- schedule_delayed_work(&dev->wqe, 1);
-
- return 0;
-
-error:
- /* Free the ressources */
- sd_stopN(gspca_dev);
- sd_stop0(gspca_dev);
- return ret;
-}
-
-/* Table of supported USB devices */
-static const __devinitdata struct usb_device_id device_table[] = {
- {USB_DEVICE(0x04cb, 0x0104)},
- {USB_DEVICE(0x04cb, 0x0109)},
- {USB_DEVICE(0x04cb, 0x010b)},
- {USB_DEVICE(0x04cb, 0x010f)},
- {USB_DEVICE(0x04cb, 0x0111)},
- {USB_DEVICE(0x04cb, 0x0113)},
- {USB_DEVICE(0x04cb, 0x0115)},
- {USB_DEVICE(0x04cb, 0x0117)},
- {USB_DEVICE(0x04cb, 0x0119)},
- {USB_DEVICE(0x04cb, 0x011b)},
- {USB_DEVICE(0x04cb, 0x011d)},
- {USB_DEVICE(0x04cb, 0x0121)},
- {USB_DEVICE(0x04cb, 0x0123)},
- {USB_DEVICE(0x04cb, 0x0125)},
- {USB_DEVICE(0x04cb, 0x0127)},
- {USB_DEVICE(0x04cb, 0x0129)},
- {USB_DEVICE(0x04cb, 0x012b)},
- {USB_DEVICE(0x04cb, 0x012d)},
- {USB_DEVICE(0x04cb, 0x012f)},
- {USB_DEVICE(0x04cb, 0x0131)},
- {USB_DEVICE(0x04cb, 0x013b)},
- {USB_DEVICE(0x04cb, 0x013d)},
- {USB_DEVICE(0x04cb, 0x013f)},
- {}
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* sub-driver description */
-static const struct sd_desc sd_desc = {
- .name = MODULE_NAME,
- .config = sd_config,
- .init = sd_init,
- .start = sd_start,
- .stopN = sd_stopN,
- .stop0 = sd_stop0,
-};
-
-/* -- 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 usb_fpix),
- THIS_MODULE);
-}
-
-static struct usb_driver sd_driver = {
- .name = MODULE_NAME,
- .id_table = device_table,
- .probe = sd_probe,
- .disconnect = gspca_disconnect,
-#ifdef CONFIG_PM
- .suspend = gspca_suspend,
- .resume = gspca_resume,
-#endif
-};
-
-/* -- module insert / remove -- */
-static int __init sd_mod_init(void)
-{
- if (usb_register(&sd_driver) < 0)
- return -1;
- PDEBUG(D_PROBE, "registered");
- return 0;
-}
-static void __exit sd_mod_exit(void)
-{
- usb_deregister(&sd_driver);
- PDEBUG(D_PROBE, "deregistered");
-}
-
-module_init(sd_mod_init);
-module_exit(sd_mod_exit);