162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Fujifilm Finepix subdriver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2008 Frank Zago
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#define MODULE_NAME "finepix"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include "gspca.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ciMODULE_AUTHOR("Frank Zago <frank@zago.net>");
1562306a36Sopenharmony_ciMODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver");
1662306a36Sopenharmony_ciMODULE_LICENSE("GPL");
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/* Default timeout, in ms */
1962306a36Sopenharmony_ci#define FPIX_TIMEOUT 250
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/* Maximum transfer size to use. The windows driver reads by chunks of
2262306a36Sopenharmony_ci * 0x2000 bytes, so do the same. Note: reading more seems to work
2362306a36Sopenharmony_ci * too. */
2462306a36Sopenharmony_ci#define FPIX_MAX_TRANSFER 0x2000
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/* Structure to hold all of our device specific stuff */
2762306a36Sopenharmony_cistruct usb_fpix {
2862306a36Sopenharmony_ci	struct gspca_dev gspca_dev;	/* !! must be the first item */
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	struct work_struct work_struct;
3162306a36Sopenharmony_ci};
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/* Delay after which claim the next frame. If the delay is too small,
3462306a36Sopenharmony_ci * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms
3562306a36Sopenharmony_ci * will fail every 4 or 5 frames, but 30ms is perfect. On the A210,
3662306a36Sopenharmony_ci * 30ms is bad while 35ms is perfect. */
3762306a36Sopenharmony_ci#define NEXT_FRAME_DELAY 35
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/* These cameras only support 320x200. */
4062306a36Sopenharmony_cistatic const struct v4l2_pix_format fpix_mode[1] = {
4162306a36Sopenharmony_ci	{ 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
4262306a36Sopenharmony_ci		.bytesperline = 320,
4362306a36Sopenharmony_ci		.sizeimage = 320 * 240 * 3 / 8 + 590,
4462306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
4562306a36Sopenharmony_ci		.priv = 0}
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci/* send a command to the webcam */
4962306a36Sopenharmony_cistatic int command(struct gspca_dev *gspca_dev,
5062306a36Sopenharmony_ci		int order)	/* 0: reset, 1: frame request */
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	static u8 order_values[2][12] = {
5362306a36Sopenharmony_ci		{0xc6, 0, 0, 0, 0, 0, 0,    0, 0x20, 0, 0, 0},	/* reset */
5462306a36Sopenharmony_ci		{0xd3, 0, 0, 0, 0, 0, 0, 0x01,    0, 0, 0, 0},	/* fr req */
5562306a36Sopenharmony_ci	};
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	memcpy(gspca_dev->usb_buf, order_values[order], 12);
5862306a36Sopenharmony_ci	return usb_control_msg(gspca_dev->dev,
5962306a36Sopenharmony_ci			usb_sndctrlpipe(gspca_dev->dev, 0),
6062306a36Sopenharmony_ci			USB_REQ_GET_STATUS,
6162306a36Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_CLASS |
6262306a36Sopenharmony_ci			USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
6362306a36Sopenharmony_ci			12, FPIX_TIMEOUT);
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci/*
6762306a36Sopenharmony_ci * This function is called as a workqueue function and runs whenever the camera
6862306a36Sopenharmony_ci * is streaming data. Because it is a workqueue function it is allowed to sleep
6962306a36Sopenharmony_ci * so we can use synchronous USB calls. To avoid possible collisions with other
7062306a36Sopenharmony_ci * threads attempting to use gspca_dev->usb_buf we take the usb_lock when
7162306a36Sopenharmony_ci * performing USB operations using it. In practice we don't really need this
7262306a36Sopenharmony_ci * as the camera doesn't provide any controls.
7362306a36Sopenharmony_ci */
7462306a36Sopenharmony_cistatic void dostream(struct work_struct *work)
7562306a36Sopenharmony_ci{
7662306a36Sopenharmony_ci	struct usb_fpix *dev = container_of(work, struct usb_fpix, work_struct);
7762306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = &dev->gspca_dev;
7862306a36Sopenharmony_ci	struct urb *urb = gspca_dev->urb[0];
7962306a36Sopenharmony_ci	u8 *data = urb->transfer_buffer;
8062306a36Sopenharmony_ci	int ret = 0;
8162306a36Sopenharmony_ci	int len;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_STREAM, "dostream started\n");
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	/* loop reading a frame */
8662306a36Sopenharmony_ciagain:
8762306a36Sopenharmony_ci	while (gspca_dev->present && gspca_dev->streaming) {
8862306a36Sopenharmony_ci#ifdef CONFIG_PM
8962306a36Sopenharmony_ci		if (gspca_dev->frozen)
9062306a36Sopenharmony_ci			break;
9162306a36Sopenharmony_ci#endif
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci		/* request a frame */
9462306a36Sopenharmony_ci		mutex_lock(&gspca_dev->usb_lock);
9562306a36Sopenharmony_ci		ret = command(gspca_dev, 1);
9662306a36Sopenharmony_ci		mutex_unlock(&gspca_dev->usb_lock);
9762306a36Sopenharmony_ci		if (ret < 0)
9862306a36Sopenharmony_ci			break;
9962306a36Sopenharmony_ci#ifdef CONFIG_PM
10062306a36Sopenharmony_ci		if (gspca_dev->frozen)
10162306a36Sopenharmony_ci			break;
10262306a36Sopenharmony_ci#endif
10362306a36Sopenharmony_ci		if (!gspca_dev->present || !gspca_dev->streaming)
10462306a36Sopenharmony_ci			break;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci		/* the frame comes in parts */
10762306a36Sopenharmony_ci		for (;;) {
10862306a36Sopenharmony_ci			ret = usb_bulk_msg(gspca_dev->dev,
10962306a36Sopenharmony_ci					urb->pipe,
11062306a36Sopenharmony_ci					data,
11162306a36Sopenharmony_ci					FPIX_MAX_TRANSFER,
11262306a36Sopenharmony_ci					&len, FPIX_TIMEOUT);
11362306a36Sopenharmony_ci			if (ret < 0) {
11462306a36Sopenharmony_ci				/* Most of the time we get a timeout
11562306a36Sopenharmony_ci				 * error. Just restart. */
11662306a36Sopenharmony_ci				goto again;
11762306a36Sopenharmony_ci			}
11862306a36Sopenharmony_ci#ifdef CONFIG_PM
11962306a36Sopenharmony_ci			if (gspca_dev->frozen)
12062306a36Sopenharmony_ci				goto out;
12162306a36Sopenharmony_ci#endif
12262306a36Sopenharmony_ci			if (!gspca_dev->present || !gspca_dev->streaming)
12362306a36Sopenharmony_ci				goto out;
12462306a36Sopenharmony_ci			if (len < FPIX_MAX_TRANSFER ||
12562306a36Sopenharmony_ci				(data[len - 2] == 0xff &&
12662306a36Sopenharmony_ci					data[len - 1] == 0xd9)) {
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci				/* If the result is less than what was asked
12962306a36Sopenharmony_ci				 * for, then it's the end of the
13062306a36Sopenharmony_ci				 * frame. Sometimes the jpeg is not complete,
13162306a36Sopenharmony_ci				 * but there's nothing we can do. We also end
13262306a36Sopenharmony_ci				 * here if the jpeg ends right at the end
13362306a36Sopenharmony_ci				 * of the frame. */
13462306a36Sopenharmony_ci				gspca_frame_add(gspca_dev, LAST_PACKET,
13562306a36Sopenharmony_ci						data, len);
13662306a36Sopenharmony_ci				break;
13762306a36Sopenharmony_ci			}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci			/* got a partial image */
14062306a36Sopenharmony_ci			gspca_frame_add(gspca_dev,
14162306a36Sopenharmony_ci					gspca_dev->last_packet_type
14262306a36Sopenharmony_ci						== LAST_PACKET
14362306a36Sopenharmony_ci					? FIRST_PACKET : INTER_PACKET,
14462306a36Sopenharmony_ci					data, len);
14562306a36Sopenharmony_ci		}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci		/* We must wait before trying reading the next
14862306a36Sopenharmony_ci		 * frame. If we don't, or if the delay is too short,
14962306a36Sopenharmony_ci		 * the camera will disconnect. */
15062306a36Sopenharmony_ci		msleep(NEXT_FRAME_DELAY);
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ciout:
15462306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_STREAM, "dostream stopped\n");
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci/* this function is called at probe time */
15862306a36Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev,
15962306a36Sopenharmony_ci		const struct usb_device_id *id)
16062306a36Sopenharmony_ci{
16162306a36Sopenharmony_ci	struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
16262306a36Sopenharmony_ci	struct cam *cam = &gspca_dev->cam;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	cam->cam_mode = fpix_mode;
16562306a36Sopenharmony_ci	cam->nmodes = 1;
16662306a36Sopenharmony_ci	cam->bulk = 1;
16762306a36Sopenharmony_ci	cam->bulk_size = FPIX_MAX_TRANSFER;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	INIT_WORK(&dev->work_struct, dostream);
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	return 0;
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci/* this function is called at probe and resume time */
17562306a36Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev)
17662306a36Sopenharmony_ci{
17762306a36Sopenharmony_ci	return 0;
17862306a36Sopenharmony_ci}
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci/* start the camera */
18162306a36Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev)
18262306a36Sopenharmony_ci{
18362306a36Sopenharmony_ci	struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
18462306a36Sopenharmony_ci	int ret, len;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	/* Init the device */
18762306a36Sopenharmony_ci	ret = command(gspca_dev, 0);
18862306a36Sopenharmony_ci	if (ret < 0) {
18962306a36Sopenharmony_ci		pr_err("init failed %d\n", ret);
19062306a36Sopenharmony_ci		return ret;
19162306a36Sopenharmony_ci	}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	/* Read the result of the command. Ignore the result, for it
19462306a36Sopenharmony_ci	 * varies with the device. */
19562306a36Sopenharmony_ci	ret = usb_bulk_msg(gspca_dev->dev,
19662306a36Sopenharmony_ci			gspca_dev->urb[0]->pipe,
19762306a36Sopenharmony_ci			gspca_dev->urb[0]->transfer_buffer,
19862306a36Sopenharmony_ci			FPIX_MAX_TRANSFER, &len,
19962306a36Sopenharmony_ci			FPIX_TIMEOUT);
20062306a36Sopenharmony_ci	if (ret < 0) {
20162306a36Sopenharmony_ci		pr_err("usb_bulk_msg failed %d\n", ret);
20262306a36Sopenharmony_ci		return ret;
20362306a36Sopenharmony_ci	}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	/* Request a frame, but don't read it */
20662306a36Sopenharmony_ci	ret = command(gspca_dev, 1);
20762306a36Sopenharmony_ci	if (ret < 0) {
20862306a36Sopenharmony_ci		pr_err("frame request failed %d\n", ret);
20962306a36Sopenharmony_ci		return ret;
21062306a36Sopenharmony_ci	}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	/* Again, reset bulk in endpoint */
21362306a36Sopenharmony_ci	usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	schedule_work(&dev->work_struct);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	return 0;
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci/* called on streamoff with alt==0 and on disconnect */
22162306a36Sopenharmony_ci/* the usb_lock is held at entry - restore on exit */
22262306a36Sopenharmony_cistatic void sd_stop0(struct gspca_dev *gspca_dev)
22362306a36Sopenharmony_ci{
22462306a36Sopenharmony_ci	struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	/* wait for the work queue to terminate */
22762306a36Sopenharmony_ci	mutex_unlock(&gspca_dev->usb_lock);
22862306a36Sopenharmony_ci	flush_work(&dev->work_struct);
22962306a36Sopenharmony_ci	mutex_lock(&gspca_dev->usb_lock);
23062306a36Sopenharmony_ci}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci/* Table of supported USB devices */
23362306a36Sopenharmony_cistatic const struct usb_device_id device_table[] = {
23462306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x0104)},
23562306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x0109)},
23662306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x010b)},
23762306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x010f)},
23862306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x0111)},
23962306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x0113)},
24062306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x0115)},
24162306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x0117)},
24262306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x0119)},
24362306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x011b)},
24462306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x011d)},
24562306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x0121)},
24662306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x0123)},
24762306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x0125)},
24862306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x0127)},
24962306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x0129)},
25062306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x012b)},
25162306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x012d)},
25262306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x012f)},
25362306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x0131)},
25462306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x013b)},
25562306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x013d)},
25662306a36Sopenharmony_ci	{USB_DEVICE(0x04cb, 0x013f)},
25762306a36Sopenharmony_ci	{}
25862306a36Sopenharmony_ci};
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci/* sub-driver description */
26362306a36Sopenharmony_cistatic const struct sd_desc sd_desc = {
26462306a36Sopenharmony_ci	.name   = MODULE_NAME,
26562306a36Sopenharmony_ci	.config = sd_config,
26662306a36Sopenharmony_ci	.init   = sd_init,
26762306a36Sopenharmony_ci	.start  = sd_start,
26862306a36Sopenharmony_ci	.stop0  = sd_stop0,
26962306a36Sopenharmony_ci};
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci/* -- device connect -- */
27262306a36Sopenharmony_cistatic int sd_probe(struct usb_interface *intf,
27362306a36Sopenharmony_ci		const struct usb_device_id *id)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	return gspca_dev_probe(intf, id,
27662306a36Sopenharmony_ci			&sd_desc,
27762306a36Sopenharmony_ci			sizeof(struct usb_fpix),
27862306a36Sopenharmony_ci			THIS_MODULE);
27962306a36Sopenharmony_ci}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_cistatic struct usb_driver sd_driver = {
28262306a36Sopenharmony_ci	.name       = MODULE_NAME,
28362306a36Sopenharmony_ci	.id_table   = device_table,
28462306a36Sopenharmony_ci	.probe      = sd_probe,
28562306a36Sopenharmony_ci	.disconnect = gspca_disconnect,
28662306a36Sopenharmony_ci#ifdef CONFIG_PM
28762306a36Sopenharmony_ci	.suspend = gspca_suspend,
28862306a36Sopenharmony_ci	.resume  = gspca_resume,
28962306a36Sopenharmony_ci	.reset_resume = gspca_resume,
29062306a36Sopenharmony_ci#endif
29162306a36Sopenharmony_ci};
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_cimodule_usb_driver(sd_driver);
294