// SPDX-License-Identifier: GPL-2.0-or-later /* * STV0680 USB Camera Driver * * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> * * This module is adapted from the in kernel v4l1 stv680 driver: * * STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net) * * Thanks to STMicroelectronics for information on the usb commands, and * to Steve Miller at STM for his help and encouragement while I was * writing this driver.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define MODULE_NAME "stv0680"
#include"gspca.h"
MODULE_AUTHOR("Hans de Goede ");
MODULE_DESCRIPTION("STV0680 USB Camera Driver");
MODULE_LICENSE("GPL");
/* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ struct v4l2_pix_format mode;
u8 orig_mode;
u8 video_mode;
u8 current_mode;
};
staticint stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val, int size)
{ int ret;
u8 req_type = 0; unsignedint pipe = 0;
staticint stv0680_handle_error(struct gspca_dev *gspca_dev, int ret)
{
stv_sndctrl(gspca_dev, 0, 0x80, 0, 0x02); /* Get Last Error */
gspca_err(gspca_dev, "last error: %i, command = 0x%x\n",
gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]); return ret;
}
staticint stv0680_get_video_mode(struct gspca_dev *gspca_dev)
{ /* Note not sure if this init of usb_buf is really necessary */
memset(gspca_dev->usb_buf, 0, 8);
gspca_dev->usb_buf[0] = 0x0f;
/* Verify we got what we've asked for */ if (stv0680_get_video_mode(gspca_dev) != mode) {
gspca_err(gspca_dev, "Error setting camera video mode!\n"); return -EIO;
}
sd->current_mode = mode;
return 0;
}
/* this function is called at probe time */ staticint sd_config(struct gspca_dev *gspca_dev, conststruct usb_device_id *id)
{ int ret; struct sd *sd = (struct sd *) gspca_dev; struct cam *cam = &gspca_dev->cam;
/* Give the camera some time to settle, otherwise initialization will
fail on hotplug, and yes it really needs a full second. */
msleep(1000);
/* ping camera to be sure STV0680 is present */ if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 ||
gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) {
gspca_err(gspca_dev, "STV(e): camera ping failed!!\n"); return stv0680_handle_error(gspca_dev, -ENODEV);
}
/* get camera descriptor */ if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x09) != 0x09) return stv0680_handle_error(gspca_dev, -ENODEV);
if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x22) != 0x22 ||
gspca_dev->usb_buf[7] != 0xa0 || gspca_dev->usb_buf[8] != 0x23) {
gspca_err(gspca_dev, "Could not get descriptor 0200\n"); return stv0680_handle_error(gspca_dev, -ENODEV);
} if (stv_sndctrl(gspca_dev, 0, 0x8a, 0, 0x02) != 0x02) return stv0680_handle_error(gspca_dev, -ENODEV); if (stv_sndctrl(gspca_dev, 0, 0x8b, 0, 0x24) != 0x24) return stv0680_handle_error(gspca_dev, -ENODEV); if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10) return stv0680_handle_error(gspca_dev, -ENODEV);
if (!(gspca_dev->usb_buf[7] & 0x09)) {
gspca_err(gspca_dev, "Camera supports neither CIF nor QVGA mode\n"); return -ENODEV;
} if (gspca_dev->usb_buf[7] & 0x01)
gspca_dbg(gspca_dev, D_PROBE, "Camera supports CIF mode\n"); if (gspca_dev->usb_buf[7] & 0x02)
gspca_dbg(gspca_dev, D_PROBE, "Camera supports VGA mode\n"); if (gspca_dev->usb_buf[7] & 0x04)
gspca_dbg(gspca_dev, D_PROBE, "Camera supports QCIF mode\n"); if (gspca_dev->usb_buf[7] & 0x08)
gspca_dbg(gspca_dev, D_PROBE, "Camera supports QVGA mode\n");
staticvoid sd_stopN(struct gspca_dev *gspca_dev)
{ /* This is a high priority command; it stops all lower order cmds */ if (stv_sndctrl(gspca_dev, 1, 0x04, 0x0000, 0x0) != 0x0)
stv0680_handle_error(gspca_dev, -EIO);
}
/* Every now and then the camera sends a 16 byte packet, no idea what it contains, but it is not image data, when this happens the frame received before this packet is corrupt,
so discard it. */ if (len != sd->mode.sizeimage) {
gspca_dev->last_packet_type = DISCARD_PACKET; return;
}
/* Finish the previous frame, we do this upon reception of the next packet, even though it is already complete so that the strange 16
byte packets send after a corrupt frame can discard it. */
gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
/* Store the just received frame */
gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.