162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * SQ905C subdriver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2009 Theodore Kilgore 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * This driver uses work done in 1162306a36Sopenharmony_ci * libgphoto2/camlibs/digigr8, Copyright (C) Theodore Kilgore. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * This driver has also used as a base the sq905c driver 1462306a36Sopenharmony_ci * and may contain code fragments from it. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define MODULE_NAME "sq905c" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include <linux/workqueue.h> 2262306a36Sopenharmony_ci#include <linux/slab.h> 2362306a36Sopenharmony_ci#include "gspca.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ciMODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>"); 2662306a36Sopenharmony_ciMODULE_DESCRIPTION("GSPCA/SQ905C USB Camera Driver"); 2762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* Default timeouts, in ms */ 3062306a36Sopenharmony_ci#define SQ905C_CMD_TIMEOUT 500 3162306a36Sopenharmony_ci#define SQ905C_DATA_TIMEOUT 1000 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* Maximum transfer size to use. */ 3462306a36Sopenharmony_ci#define SQ905C_MAX_TRANSFER 0x8000 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define FRAME_HEADER_LEN 0x50 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* Commands. These go in the "value" slot. */ 3962306a36Sopenharmony_ci#define SQ905C_CLEAR 0xa0 /* clear everything */ 4062306a36Sopenharmony_ci#define SQ905C_GET_ID 0x14f4 /* Read version number */ 4162306a36Sopenharmony_ci#define SQ905C_CAPTURE_LOW 0xa040 /* Starts capture at 160x120 */ 4262306a36Sopenharmony_ci#define SQ905C_CAPTURE_MED 0x1440 /* Starts capture at 320x240 */ 4362306a36Sopenharmony_ci#define SQ905C_CAPTURE_HI 0x2840 /* Starts capture at 320x240 */ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* For capture, this must go in the "index" slot. */ 4662306a36Sopenharmony_ci#define SQ905C_CAPTURE_INDEX 0x110f 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* Structure to hold all of our device specific stuff */ 4962306a36Sopenharmony_cistruct sd { 5062306a36Sopenharmony_ci struct gspca_dev gspca_dev; /* !! must be the first item */ 5162306a36Sopenharmony_ci const struct v4l2_pix_format *cap_mode; 5262306a36Sopenharmony_ci /* Driver stuff */ 5362306a36Sopenharmony_ci struct work_struct work_struct; 5462306a36Sopenharmony_ci struct workqueue_struct *work_thread; 5562306a36Sopenharmony_ci}; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* 5862306a36Sopenharmony_ci * Most of these cameras will do 640x480 and 320x240. 160x120 works 5962306a36Sopenharmony_ci * in theory but gives very poor output. Therefore, not supported. 6062306a36Sopenharmony_ci * The 0x2770:0x9050 cameras have max resolution of 320x240. 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_cistatic struct v4l2_pix_format sq905c_mode[] = { 6362306a36Sopenharmony_ci { 320, 240, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE, 6462306a36Sopenharmony_ci .bytesperline = 320, 6562306a36Sopenharmony_ci .sizeimage = 320 * 240, 6662306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 6762306a36Sopenharmony_ci .priv = 0}, 6862306a36Sopenharmony_ci { 640, 480, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE, 6962306a36Sopenharmony_ci .bytesperline = 640, 7062306a36Sopenharmony_ci .sizeimage = 640 * 480, 7162306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 7262306a36Sopenharmony_ci .priv = 0} 7362306a36Sopenharmony_ci}; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci/* Send a command to the camera. */ 7662306a36Sopenharmony_cistatic int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci int ret; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci ret = usb_control_msg(gspca_dev->dev, 8162306a36Sopenharmony_ci usb_sndctrlpipe(gspca_dev->dev, 0), 8262306a36Sopenharmony_ci USB_REQ_SYNCH_FRAME, /* request */ 8362306a36Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 8462306a36Sopenharmony_ci command, index, NULL, 0, 8562306a36Sopenharmony_ci SQ905C_CMD_TIMEOUT); 8662306a36Sopenharmony_ci if (ret < 0) { 8762306a36Sopenharmony_ci pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret); 8862306a36Sopenharmony_ci return ret; 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci return 0; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index, 9562306a36Sopenharmony_ci int size) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci int ret; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci ret = usb_control_msg(gspca_dev->dev, 10062306a36Sopenharmony_ci usb_rcvctrlpipe(gspca_dev->dev, 0), 10162306a36Sopenharmony_ci USB_REQ_SYNCH_FRAME, /* request */ 10262306a36Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 10362306a36Sopenharmony_ci command, index, gspca_dev->usb_buf, size, 10462306a36Sopenharmony_ci SQ905C_CMD_TIMEOUT); 10562306a36Sopenharmony_ci if (ret < 0) { 10662306a36Sopenharmony_ci pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret); 10762306a36Sopenharmony_ci return ret; 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci return 0; 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci/* 11462306a36Sopenharmony_ci * This function is called as a workqueue function and runs whenever the camera 11562306a36Sopenharmony_ci * is streaming data. Because it is a workqueue function it is allowed to sleep 11662306a36Sopenharmony_ci * so we can use synchronous USB calls. To avoid possible collisions with other 11762306a36Sopenharmony_ci * threads attempting to use gspca_dev->usb_buf we take the usb_lock when 11862306a36Sopenharmony_ci * performing USB operations using it. In practice we don't really need this 11962306a36Sopenharmony_ci * as the camera doesn't provide any controls. 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_cistatic void sq905c_dostream(struct work_struct *work) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci struct sd *dev = container_of(work, struct sd, work_struct); 12462306a36Sopenharmony_ci struct gspca_dev *gspca_dev = &dev->gspca_dev; 12562306a36Sopenharmony_ci int bytes_left; /* bytes remaining in current frame. */ 12662306a36Sopenharmony_ci int data_len; /* size to use for the next read. */ 12762306a36Sopenharmony_ci int act_len; 12862306a36Sopenharmony_ci int packet_type; 12962306a36Sopenharmony_ci int ret; 13062306a36Sopenharmony_ci u8 *buffer; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL); 13362306a36Sopenharmony_ci if (!buffer) { 13462306a36Sopenharmony_ci pr_err("Couldn't allocate USB buffer\n"); 13562306a36Sopenharmony_ci goto quit_stream; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci while (gspca_dev->present && gspca_dev->streaming) { 13962306a36Sopenharmony_ci#ifdef CONFIG_PM 14062306a36Sopenharmony_ci if (gspca_dev->frozen) 14162306a36Sopenharmony_ci break; 14262306a36Sopenharmony_ci#endif 14362306a36Sopenharmony_ci /* Request the header, which tells the size to download */ 14462306a36Sopenharmony_ci ret = usb_bulk_msg(gspca_dev->dev, 14562306a36Sopenharmony_ci usb_rcvbulkpipe(gspca_dev->dev, 0x81), 14662306a36Sopenharmony_ci buffer, FRAME_HEADER_LEN, &act_len, 14762306a36Sopenharmony_ci SQ905C_DATA_TIMEOUT); 14862306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, 14962306a36Sopenharmony_ci "Got %d bytes out of %d for header\n", 15062306a36Sopenharmony_ci act_len, FRAME_HEADER_LEN); 15162306a36Sopenharmony_ci if (ret < 0 || act_len < FRAME_HEADER_LEN) 15262306a36Sopenharmony_ci goto quit_stream; 15362306a36Sopenharmony_ci /* size is read from 4 bytes starting 0x40, little endian */ 15462306a36Sopenharmony_ci bytes_left = buffer[0x40]|(buffer[0x41]<<8)|(buffer[0x42]<<16) 15562306a36Sopenharmony_ci |(buffer[0x43]<<24); 15662306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "bytes_left = 0x%x\n", 15762306a36Sopenharmony_ci bytes_left); 15862306a36Sopenharmony_ci /* We keep the header. It has other information, too. */ 15962306a36Sopenharmony_ci packet_type = FIRST_PACKET; 16062306a36Sopenharmony_ci gspca_frame_add(gspca_dev, packet_type, 16162306a36Sopenharmony_ci buffer, FRAME_HEADER_LEN); 16262306a36Sopenharmony_ci while (bytes_left > 0 && gspca_dev->present) { 16362306a36Sopenharmony_ci data_len = bytes_left > SQ905C_MAX_TRANSFER ? 16462306a36Sopenharmony_ci SQ905C_MAX_TRANSFER : bytes_left; 16562306a36Sopenharmony_ci ret = usb_bulk_msg(gspca_dev->dev, 16662306a36Sopenharmony_ci usb_rcvbulkpipe(gspca_dev->dev, 0x81), 16762306a36Sopenharmony_ci buffer, data_len, &act_len, 16862306a36Sopenharmony_ci SQ905C_DATA_TIMEOUT); 16962306a36Sopenharmony_ci if (ret < 0 || act_len < data_len) 17062306a36Sopenharmony_ci goto quit_stream; 17162306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, 17262306a36Sopenharmony_ci "Got %d bytes out of %d for frame\n", 17362306a36Sopenharmony_ci data_len, bytes_left); 17462306a36Sopenharmony_ci bytes_left -= data_len; 17562306a36Sopenharmony_ci if (bytes_left == 0) 17662306a36Sopenharmony_ci packet_type = LAST_PACKET; 17762306a36Sopenharmony_ci else 17862306a36Sopenharmony_ci packet_type = INTER_PACKET; 17962306a36Sopenharmony_ci gspca_frame_add(gspca_dev, packet_type, 18062306a36Sopenharmony_ci buffer, data_len); 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ciquit_stream: 18462306a36Sopenharmony_ci if (gspca_dev->present) { 18562306a36Sopenharmony_ci mutex_lock(&gspca_dev->usb_lock); 18662306a36Sopenharmony_ci sq905c_command(gspca_dev, SQ905C_CLEAR, 0); 18762306a36Sopenharmony_ci mutex_unlock(&gspca_dev->usb_lock); 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci kfree(buffer); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci/* This function is called at probe time just before sd_init */ 19362306a36Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev, 19462306a36Sopenharmony_ci const struct usb_device_id *id) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci struct cam *cam = &gspca_dev->cam; 19762306a36Sopenharmony_ci struct sd *dev = (struct sd *) gspca_dev; 19862306a36Sopenharmony_ci int ret; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, 20162306a36Sopenharmony_ci "SQ9050 camera detected (vid/pid 0x%04X:0x%04X)\n", 20262306a36Sopenharmony_ci id->idVendor, id->idProduct); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci ret = sq905c_command(gspca_dev, SQ905C_GET_ID, 0); 20562306a36Sopenharmony_ci if (ret < 0) { 20662306a36Sopenharmony_ci gspca_err(gspca_dev, "Get version command failed\n"); 20762306a36Sopenharmony_ci return ret; 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci ret = sq905c_read(gspca_dev, 0xf5, 0, 20); 21162306a36Sopenharmony_ci if (ret < 0) { 21262306a36Sopenharmony_ci gspca_err(gspca_dev, "Reading version command failed\n"); 21362306a36Sopenharmony_ci return ret; 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci /* Note we leave out the usb id and the manufacturing date */ 21662306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, 21762306a36Sopenharmony_ci "SQ9050 ID string: %02x - %*ph\n", 21862306a36Sopenharmony_ci gspca_dev->usb_buf[3], 6, gspca_dev->usb_buf + 14); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci cam->cam_mode = sq905c_mode; 22162306a36Sopenharmony_ci cam->nmodes = 2; 22262306a36Sopenharmony_ci if (gspca_dev->usb_buf[15] == 0) 22362306a36Sopenharmony_ci cam->nmodes = 1; 22462306a36Sopenharmony_ci /* We don't use the buffer gspca allocates so make it small. */ 22562306a36Sopenharmony_ci cam->bulk_size = 32; 22662306a36Sopenharmony_ci cam->bulk = 1; 22762306a36Sopenharmony_ci INIT_WORK(&dev->work_struct, sq905c_dostream); 22862306a36Sopenharmony_ci return 0; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci/* called on streamoff with alt==0 and on disconnect */ 23262306a36Sopenharmony_ci/* the usb_lock is held at entry - restore on exit */ 23362306a36Sopenharmony_cistatic void sd_stop0(struct gspca_dev *gspca_dev) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci struct sd *dev = (struct sd *) gspca_dev; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci /* wait for the work queue to terminate */ 23862306a36Sopenharmony_ci mutex_unlock(&gspca_dev->usb_lock); 23962306a36Sopenharmony_ci /* This waits for sq905c_dostream to finish */ 24062306a36Sopenharmony_ci destroy_workqueue(dev->work_thread); 24162306a36Sopenharmony_ci dev->work_thread = NULL; 24262306a36Sopenharmony_ci mutex_lock(&gspca_dev->usb_lock); 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci/* this function is called at probe and resume time */ 24662306a36Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci /* connect to the camera and reset it. */ 24962306a36Sopenharmony_ci return sq905c_command(gspca_dev, SQ905C_CLEAR, 0); 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci/* Set up for getting frames. */ 25362306a36Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev) 25462306a36Sopenharmony_ci{ 25562306a36Sopenharmony_ci struct sd *dev = (struct sd *) gspca_dev; 25662306a36Sopenharmony_ci int ret; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci dev->cap_mode = gspca_dev->cam.cam_mode; 25962306a36Sopenharmony_ci /* "Open the shutter" and set size, to start capture */ 26062306a36Sopenharmony_ci switch (gspca_dev->pixfmt.width) { 26162306a36Sopenharmony_ci case 640: 26262306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "Start streaming at high resolution\n"); 26362306a36Sopenharmony_ci dev->cap_mode++; 26462306a36Sopenharmony_ci ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_HI, 26562306a36Sopenharmony_ci SQ905C_CAPTURE_INDEX); 26662306a36Sopenharmony_ci break; 26762306a36Sopenharmony_ci default: /* 320 */ 26862306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "Start streaming at medium resolution\n"); 26962306a36Sopenharmony_ci ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_MED, 27062306a36Sopenharmony_ci SQ905C_CAPTURE_INDEX); 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci if (ret < 0) { 27462306a36Sopenharmony_ci gspca_err(gspca_dev, "Start streaming command failed\n"); 27562306a36Sopenharmony_ci return ret; 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci /* Start the workqueue function to do the streaming */ 27862306a36Sopenharmony_ci dev->work_thread = create_singlethread_workqueue(MODULE_NAME); 27962306a36Sopenharmony_ci if (!dev->work_thread) 28062306a36Sopenharmony_ci return -ENOMEM; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci queue_work(dev->work_thread, &dev->work_struct); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci return 0; 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci/* Table of supported USB devices */ 28862306a36Sopenharmony_cistatic const struct usb_device_id device_table[] = { 28962306a36Sopenharmony_ci {USB_DEVICE(0x2770, 0x905c)}, 29062306a36Sopenharmony_ci {USB_DEVICE(0x2770, 0x9050)}, 29162306a36Sopenharmony_ci {USB_DEVICE(0x2770, 0x9051)}, 29262306a36Sopenharmony_ci {USB_DEVICE(0x2770, 0x9052)}, 29362306a36Sopenharmony_ci {USB_DEVICE(0x2770, 0x913d)}, 29462306a36Sopenharmony_ci {} 29562306a36Sopenharmony_ci}; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci/* sub-driver description */ 30062306a36Sopenharmony_cistatic const struct sd_desc sd_desc = { 30162306a36Sopenharmony_ci .name = MODULE_NAME, 30262306a36Sopenharmony_ci .config = sd_config, 30362306a36Sopenharmony_ci .init = sd_init, 30462306a36Sopenharmony_ci .start = sd_start, 30562306a36Sopenharmony_ci .stop0 = sd_stop0, 30662306a36Sopenharmony_ci}; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci/* -- device connect -- */ 30962306a36Sopenharmony_cistatic int sd_probe(struct usb_interface *intf, 31062306a36Sopenharmony_ci const struct usb_device_id *id) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci return gspca_dev_probe(intf, id, 31362306a36Sopenharmony_ci &sd_desc, 31462306a36Sopenharmony_ci sizeof(struct sd), 31562306a36Sopenharmony_ci THIS_MODULE); 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_cistatic struct usb_driver sd_driver = { 31962306a36Sopenharmony_ci .name = MODULE_NAME, 32062306a36Sopenharmony_ci .id_table = device_table, 32162306a36Sopenharmony_ci .probe = sd_probe, 32262306a36Sopenharmony_ci .disconnect = gspca_disconnect, 32362306a36Sopenharmony_ci#ifdef CONFIG_PM 32462306a36Sopenharmony_ci .suspend = gspca_suspend, 32562306a36Sopenharmony_ci .resume = gspca_resume, 32662306a36Sopenharmony_ci .reset_resume = gspca_resume, 32762306a36Sopenharmony_ci#endif 32862306a36Sopenharmony_ci}; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cimodule_usb_driver(sd_driver); 331