^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Jeilinj subdriver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Supports some Jeilin dual-mode cameras which use bulk transport and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * download raw JPEG data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2009 Theodore Kilgore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Sportscam DV15 support and control settings are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 2011 Patrice Chotard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define MODULE_NAME "jeilinj"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "gspca.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "jpeg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* Default timeouts, in ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define JEILINJ_CMD_TIMEOUT 500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define JEILINJ_CMD_DELAY 160
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define JEILINJ_DATA_TIMEOUT 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* Maximum transfer size to use. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define JEILINJ_MAX_TRANSFER 0x200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define FRAME_HEADER_LEN 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define FRAME_START 0xFFFFFFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) SAKAR_57379,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) SPORTSCAM_DV15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define CAMQUALITY_MIN 0 /* highest cam quality */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define CAMQUALITY_MAX 97 /* lowest cam quality */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* Structure to hold all of our device specific stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct sd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct gspca_dev gspca_dev; /* !! must be the first item */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) int blocks_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) const struct v4l2_pix_format *cap_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct v4l2_ctrl *freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct v4l2_ctrl *jpegqual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* Driver stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u8 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u8 quality; /* image quality */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define QUALITY_MIN 35
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define QUALITY_MAX 85
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define QUALITY_DEF 85
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u8 jpeg_hdr[JPEG_HDR_SZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct jlj_command {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned char instruction[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned char ack_wanted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned char delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* AFAICT these cameras will only do 320x240. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static struct v4l2_pix_format jlj_mode[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .bytesperline = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) .sizeimage = 320 * 240,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .colorspace = V4L2_COLORSPACE_JPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .priv = 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) { 640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .bytesperline = 640,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .sizeimage = 640 * 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .colorspace = V4L2_COLORSPACE_JPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .priv = 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * and 0x82 for bulk transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* All commands are two bytes only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (gspca_dev->usb_err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) memcpy(gspca_dev->usb_buf, command, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) retval = usb_bulk_msg(gspca_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) usb_sndbulkpipe(gspca_dev->dev, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) gspca_dev->usb_buf, 2, NULL, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (retval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) pr_err("command write [%02x] error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) gspca_dev->usb_buf[0], retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) gspca_dev->usb_err = retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* Responses are one byte only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char *response)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (gspca_dev->usb_err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) retval = usb_bulk_msg(gspca_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) usb_rcvbulkpipe(gspca_dev->dev, 0x84),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) gspca_dev->usb_buf, 1, NULL, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *response = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (retval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) pr_err("read command [%02x] error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) gspca_dev->usb_buf[0], retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) gspca_dev->usb_err = retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void setfreq(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) u8 freq_commands[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {0x71, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {0x70, 0x07}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) freq_commands[0][1] |= val >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) jlj_write2(gspca_dev, freq_commands[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) jlj_write2(gspca_dev, freq_commands[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static void setcamquality(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) u8 quality_commands[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {0x71, 0x1E},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {0x70, 0x06}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) u8 camquality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* adapt camera quality from jpeg quality */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) camquality = ((QUALITY_MAX - val) * CAMQUALITY_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) / (QUALITY_MAX - QUALITY_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) quality_commands[0][1] += camquality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) jlj_write2(gspca_dev, quality_commands[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) jlj_write2(gspca_dev, quality_commands[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static void setautogain(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) u8 autogain_commands[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {0x94, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {0xcf, 0x00}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) autogain_commands[1][1] = val << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) jlj_write2(gspca_dev, autogain_commands[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) jlj_write2(gspca_dev, autogain_commands[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static void setred(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) u8 setred_commands[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {0x94, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {0xe6, 0x00}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) setred_commands[1][1] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) jlj_write2(gspca_dev, setred_commands[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) jlj_write2(gspca_dev, setred_commands[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static void setgreen(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) u8 setgreen_commands[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {0x94, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {0xe7, 0x00}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) setgreen_commands[1][1] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) jlj_write2(gspca_dev, setgreen_commands[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) jlj_write2(gspca_dev, setgreen_commands[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static void setblue(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) u8 setblue_commands[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {0x94, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {0xe9, 0x00}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) setblue_commands[1][1] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) jlj_write2(gspca_dev, setblue_commands[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) jlj_write2(gspca_dev, setblue_commands[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static int jlj_start(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) int start_commands_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) u8 response = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct jlj_command start_commands[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {{0x71, 0x81}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {{0x70, 0x05}, 0, JEILINJ_CMD_DELAY},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {{0x95, 0x70}, 1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {{0x71, 0x81 - gspca_dev->curr_mode}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {{0x70, 0x04}, 0, JEILINJ_CMD_DELAY},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {{0x95, 0x70}, 1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {{0x71, 0x00}, 0, 0}, /* start streaming ??*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {{0x70, 0x08}, 0, JEILINJ_CMD_DELAY},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {{0x95, 0x70}, 1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) #define SPORTSCAM_DV15_CMD_SIZE 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {{0x94, 0x02}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {{0xde, 0x24}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {{0x94, 0x02}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {{0xdd, 0xf0}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {{0x94, 0x02}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {{0xe3, 0x2c}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {{0x94, 0x02}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {{0xe4, 0x00}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {{0x94, 0x02}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {{0xe5, 0x00}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {{0x94, 0x02}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {{0xe6, 0x2c}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {{0x94, 0x03}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {{0xaa, 0x00}, 0, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) sd->blocks_left = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* Under Windows, USB spy shows that only the 9 first start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * commands are used for SPORTSCAM_DV15 webcam
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (sd->type == SPORTSCAM_DV15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) start_commands_size = SPORTSCAM_DV15_CMD_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) start_commands_size = ARRAY_SIZE(start_commands);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) for (i = 0; i < start_commands_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) jlj_write2(gspca_dev, start_commands[i].instruction);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (start_commands[i].delay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) msleep(start_commands[i].delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (start_commands[i].ack_wanted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) jlj_read1(gspca_dev, &response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) setcamquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) msleep(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (gspca_dev->usb_err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) gspca_err(gspca_dev, "Start streaming command failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static void sd_pkt_scan(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) u8 *data, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int packet_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) u32 header_marker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) gspca_dbg(gspca_dev, D_STREAM, "Got %d bytes out of %d for Block 0\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) len, JEILINJ_MAX_TRANSFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (len != JEILINJ_MAX_TRANSFER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) gspca_dbg(gspca_dev, D_PACK, "bad length\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) goto discard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* check if it's start of frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) header_marker = ((u32 *)data)[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (header_marker == FRAME_START) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) sd->blocks_left = data[0x0a] - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) gspca_dbg(gspca_dev, D_STREAM, "blocks_left = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) sd->blocks_left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* Start a new frame, and add the JPEG header, first thing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) gspca_frame_add(gspca_dev, FIRST_PACKET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) sd->jpeg_hdr, JPEG_HDR_SZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) /* Toss line 0 of data block 0, keep the rest. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) gspca_frame_add(gspca_dev, INTER_PACKET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) data + FRAME_HEADER_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) } else if (sd->blocks_left > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) gspca_dbg(gspca_dev, D_STREAM, "%d blocks remaining for frame\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) sd->blocks_left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) sd->blocks_left -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (sd->blocks_left == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) packet_type = LAST_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) packet_type = INTER_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) gspca_frame_add(gspca_dev, packet_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) data, JEILINJ_MAX_TRANSFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) goto discard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) discard:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /* Discard data until a new frame starts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) gspca_dev->last_packet_type = DISCARD_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /* This function is called at probe time just before sd_init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static int sd_config(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct cam *cam = &gspca_dev->cam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct sd *dev = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) dev->type = id->driver_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) dev->quality = QUALITY_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) cam->cam_mode = jlj_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) cam->nmodes = ARRAY_SIZE(jlj_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) cam->bulk = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) cam->bulk_nurbs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) cam->bulk_size = JEILINJ_MAX_TRANSFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static void sd_stopN(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static u8 stop_commands[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {0x71, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {0x70, 0x09},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {0x71, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {0x70, 0x05}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* get the image remaining blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) usb_bulk_msg(gspca_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) gspca_dev->urb[0]->pipe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) gspca_dev->urb[0]->transfer_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) JEILINJ_MAX_TRANSFER, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) JEILINJ_DATA_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /* search for 0xff 0xd9 (EOF for JPEG) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) buf = gspca_dev->urb[0]->transfer_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) while ((i < (JEILINJ_MAX_TRANSFER - 1)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) ((buf[i] != 0xff) || (buf[i+1] != 0xd9)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (i != (JEILINJ_MAX_TRANSFER - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /* last remaining block found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) for (i = 0; i < ARRAY_SIZE(stop_commands); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) jlj_write2(gspca_dev, stop_commands[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* this function is called at probe and resume time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static int sd_init(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* Set up for getting frames. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static int sd_start(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct sd *dev = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /* create the JPEG header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) jpeg_define(dev->jpeg_hdr, gspca_dev->pixfmt.height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) gspca_dev->pixfmt.width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 0x21); /* JPEG 422 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) jpeg_set_qual(dev->jpeg_hdr, dev->quality);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) gspca_dbg(gspca_dev, D_STREAM, "Start streaming at %dx%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) gspca_dev->pixfmt.height, gspca_dev->pixfmt.width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) jlj_start(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /* Table of supported USB devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static const struct usb_device_id device_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {USB_DEVICE(0x0979, 0x0280), .driver_info = SAKAR_57379},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {USB_DEVICE(0x0979, 0x0270), .driver_info = SPORTSCAM_DV15},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) MODULE_DEVICE_TABLE(usb, device_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct gspca_dev *gspca_dev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) struct sd *sd = (struct sd *)gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) gspca_dev->usb_err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (!gspca_dev->streaming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) case V4L2_CID_POWER_LINE_FREQUENCY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) setfreq(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) case V4L2_CID_RED_BALANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) setred(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) case V4L2_CID_GAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) setgreen(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) case V4L2_CID_BLUE_BALANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) setblue(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) case V4L2_CID_AUTOGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) setautogain(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) case V4L2_CID_JPEG_COMPRESSION_QUALITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) jpeg_set_qual(sd->jpeg_hdr, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) setcamquality(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static const struct v4l2_ctrl_ops sd_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) .s_ctrl = sd_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static int sd_init_controls(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct sd *sd = (struct sd *)gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) static const struct v4l2_ctrl_config custom_autogain = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) .ops = &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) .id = V4L2_CID_AUTOGAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) .name = "Automatic Gain (and Exposure)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) .max = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) .def = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) gspca_dev->vdev.ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) v4l2_ctrl_handler_init(hdl, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) V4L2_CID_POWER_LINE_FREQUENCY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) V4L2_CID_POWER_LINE_FREQUENCY_60HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) v4l2_ctrl_new_custom(hdl, &custom_autogain, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) V4L2_CID_RED_BALANCE, 0, 3, 1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) V4L2_CID_GAIN, 0, 3, 1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) V4L2_CID_BLUE_BALANCE, 0, 3, 1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) V4L2_CID_JPEG_COMPRESSION_QUALITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (hdl->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) pr_err("Could not initialize controls\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static int sd_set_jcomp(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) const struct v4l2_jpegcompression *jcomp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static int sd_get_jcomp(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct v4l2_jpegcompression *jcomp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) memset(jcomp, 0, sizeof *jcomp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) | V4L2_JPEG_MARKER_DQT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /* sub-driver description */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static const struct sd_desc sd_desc_sakar_57379 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) .name = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) .config = sd_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) .init = sd_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) .start = sd_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) .stopN = sd_stopN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) .pkt_scan = sd_pkt_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /* sub-driver description */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static const struct sd_desc sd_desc_sportscam_dv15 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) .name = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) .config = sd_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) .init = sd_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) .init_controls = sd_init_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) .start = sd_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) .stopN = sd_stopN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) .pkt_scan = sd_pkt_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) .get_jcomp = sd_get_jcomp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) .set_jcomp = sd_set_jcomp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) static const struct sd_desc *sd_desc[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) &sd_desc_sakar_57379,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) &sd_desc_sportscam_dv15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /* -- device connect -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static int sd_probe(struct usb_interface *intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return gspca_dev_probe(intf, id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) sd_desc[id->driver_info],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) sizeof(struct sd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static struct usb_driver sd_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) .name = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) .id_table = device_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) .probe = sd_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) .disconnect = gspca_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) .suspend = gspca_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) .resume = gspca_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) .reset_resume = gspca_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) module_usb_driver(sd_driver);