cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

jl2005bcd.c (13200B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Jeilin JL2005B/C/D library
      4 *
      5 * Copyright (C) 2011 Theodore Kilgore <kilgota@auburn.edu>
      6 */
      7
      8#define MODULE_NAME "jl2005bcd"
      9
     10#include <linux/workqueue.h>
     11#include <linux/slab.h>
     12#include "gspca.h"
     13
     14
     15MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
     16MODULE_DESCRIPTION("JL2005B/C/D USB Camera Driver");
     17MODULE_LICENSE("GPL");
     18
     19/* Default timeouts, in ms */
     20#define JL2005C_CMD_TIMEOUT 500
     21#define JL2005C_DATA_TIMEOUT 1000
     22
     23/* Maximum transfer size to use. */
     24#define JL2005C_MAX_TRANSFER 0x200
     25#define FRAME_HEADER_LEN 16
     26
     27
     28/* specific webcam descriptor */
     29struct sd {
     30	struct gspca_dev gspca_dev;  /* !! must be the first item */
     31	unsigned char firmware_id[6];
     32	const struct v4l2_pix_format *cap_mode;
     33	/* Driver stuff */
     34	struct work_struct work_struct;
     35	u8 frame_brightness;
     36	int block_size;	/* block size of camera */
     37	int vga;	/* 1 if vga cam, 0 if cif cam */
     38};
     39
     40
     41/* Camera has two resolution settings. What they are depends on model. */
     42static const struct v4l2_pix_format cif_mode[] = {
     43	{176, 144, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
     44		.bytesperline = 176,
     45		.sizeimage = 176 * 144,
     46		.colorspace = V4L2_COLORSPACE_SRGB,
     47		.priv = 0},
     48	{352, 288, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
     49		.bytesperline = 352,
     50		.sizeimage = 352 * 288,
     51		.colorspace = V4L2_COLORSPACE_SRGB,
     52		.priv = 0},
     53};
     54
     55static const struct v4l2_pix_format vga_mode[] = {
     56	{320, 240, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
     57		.bytesperline = 320,
     58		.sizeimage = 320 * 240,
     59		.colorspace = V4L2_COLORSPACE_SRGB,
     60		.priv = 0},
     61	{640, 480, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
     62		.bytesperline = 640,
     63		.sizeimage = 640 * 480,
     64		.colorspace = V4L2_COLORSPACE_SRGB,
     65		.priv = 0},
     66};
     67
     68/*
     69 * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
     70 * and 0x82 for bulk data transfer.
     71 */
     72
     73/* All commands are two bytes only */
     74static int jl2005c_write2(struct gspca_dev *gspca_dev, unsigned char *command)
     75{
     76	int retval;
     77
     78	memcpy(gspca_dev->usb_buf, command, 2);
     79	retval = usb_bulk_msg(gspca_dev->dev,
     80			usb_sndbulkpipe(gspca_dev->dev, 3),
     81			gspca_dev->usb_buf, 2, NULL, 500);
     82	if (retval < 0)
     83		pr_err("command write [%02x] error %d\n",
     84		       gspca_dev->usb_buf[0], retval);
     85	return retval;
     86}
     87
     88/* Response to a command is one byte in usb_buf[0], only if requested. */
     89static int jl2005c_read1(struct gspca_dev *gspca_dev)
     90{
     91	int retval;
     92
     93	retval = usb_bulk_msg(gspca_dev->dev,
     94				usb_rcvbulkpipe(gspca_dev->dev, 0x84),
     95				gspca_dev->usb_buf, 1, NULL, 500);
     96	if (retval < 0)
     97		pr_err("read command [0x%02x] error %d\n",
     98		       gspca_dev->usb_buf[0], retval);
     99	return retval;
    100}
    101
    102/* Response appears in gspca_dev->usb_buf[0] */
    103static int jl2005c_read_reg(struct gspca_dev *gspca_dev, unsigned char reg)
    104{
    105	int retval;
    106
    107	static u8 instruction[2] = {0x95, 0x00};
    108	/* put register to read in byte 1 */
    109	instruction[1] = reg;
    110	/* Send the read request */
    111	retval = jl2005c_write2(gspca_dev, instruction);
    112	if (retval < 0)
    113		return retval;
    114	retval = jl2005c_read1(gspca_dev);
    115
    116	return retval;
    117}
    118
    119static int jl2005c_start_new_frame(struct gspca_dev *gspca_dev)
    120{
    121	int i;
    122	int retval;
    123	int frame_brightness = 0;
    124
    125	static u8 instruction[2] = {0x7f, 0x01};
    126
    127	retval = jl2005c_write2(gspca_dev, instruction);
    128	if (retval < 0)
    129		return retval;
    130
    131	i = 0;
    132	while (i < 20 && !frame_brightness) {
    133		/* If we tried 20 times, give up. */
    134		retval = jl2005c_read_reg(gspca_dev, 0x7e);
    135		if (retval < 0)
    136			return retval;
    137		frame_brightness = gspca_dev->usb_buf[0];
    138		retval = jl2005c_read_reg(gspca_dev, 0x7d);
    139		if (retval < 0)
    140			return retval;
    141		i++;
    142	}
    143	gspca_dbg(gspca_dev, D_FRAM, "frame_brightness is 0x%02x\n",
    144		  gspca_dev->usb_buf[0]);
    145	return retval;
    146}
    147
    148static int jl2005c_write_reg(struct gspca_dev *gspca_dev, unsigned char reg,
    149						    unsigned char value)
    150{
    151	int retval;
    152	u8 instruction[2];
    153
    154	instruction[0] = reg;
    155	instruction[1] = value;
    156
    157	retval = jl2005c_write2(gspca_dev, instruction);
    158	if (retval < 0)
    159			return retval;
    160
    161	return retval;
    162}
    163
    164static int jl2005c_get_firmware_id(struct gspca_dev *gspca_dev)
    165{
    166	struct sd *sd = (struct sd *)gspca_dev;
    167	int i = 0;
    168	int retval;
    169	static const unsigned char regs_to_read[] = {
    170		0x57, 0x02, 0x03, 0x5d, 0x5e, 0x5f
    171	};
    172
    173	gspca_dbg(gspca_dev, D_PROBE, "Running jl2005c_get_firmware_id\n");
    174	/* Read the first ID byte once for warmup */
    175	retval = jl2005c_read_reg(gspca_dev, regs_to_read[0]);
    176	gspca_dbg(gspca_dev, D_PROBE, "response is %02x\n",
    177		  gspca_dev->usb_buf[0]);
    178	if (retval < 0)
    179		return retval;
    180	/* Now actually get the ID string */
    181	for (i = 0; i < 6; i++) {
    182		retval = jl2005c_read_reg(gspca_dev, regs_to_read[i]);
    183		if (retval < 0)
    184			return retval;
    185		sd->firmware_id[i] = gspca_dev->usb_buf[0];
    186	}
    187	gspca_dbg(gspca_dev, D_PROBE, "firmware ID is %02x%02x%02x%02x%02x%02x\n",
    188		  sd->firmware_id[0],
    189		  sd->firmware_id[1],
    190		  sd->firmware_id[2],
    191		  sd->firmware_id[3],
    192		  sd->firmware_id[4],
    193		  sd->firmware_id[5]);
    194	return 0;
    195}
    196
    197static int jl2005c_stream_start_vga_lg
    198		    (struct gspca_dev *gspca_dev)
    199{
    200	int i;
    201	int retval = -1;
    202	static u8 instruction[][2] = {
    203		{0x05, 0x00},
    204		{0x7c, 0x00},
    205		{0x7d, 0x18},
    206		{0x02, 0x00},
    207		{0x01, 0x00},
    208		{0x04, 0x52},
    209	};
    210
    211	for (i = 0; i < ARRAY_SIZE(instruction); i++) {
    212		msleep(60);
    213		retval = jl2005c_write2(gspca_dev, instruction[i]);
    214		if (retval < 0)
    215			return retval;
    216	}
    217	msleep(60);
    218	return retval;
    219}
    220
    221static int jl2005c_stream_start_vga_small(struct gspca_dev *gspca_dev)
    222{
    223	int i;
    224	int retval = -1;
    225	static u8 instruction[][2] = {
    226		{0x06, 0x00},
    227		{0x7c, 0x00},
    228		{0x7d, 0x1a},
    229		{0x02, 0x00},
    230		{0x01, 0x00},
    231		{0x04, 0x52},
    232	};
    233
    234	for (i = 0; i < ARRAY_SIZE(instruction); i++) {
    235		msleep(60);
    236		retval = jl2005c_write2(gspca_dev, instruction[i]);
    237		if (retval < 0)
    238			return retval;
    239	}
    240	msleep(60);
    241	return retval;
    242}
    243
    244static int jl2005c_stream_start_cif_lg(struct gspca_dev *gspca_dev)
    245{
    246	int i;
    247	int retval = -1;
    248	static u8 instruction[][2] = {
    249		{0x05, 0x00},
    250		{0x7c, 0x00},
    251		{0x7d, 0x30},
    252		{0x02, 0x00},
    253		{0x01, 0x00},
    254		{0x04, 0x42},
    255	};
    256
    257	for (i = 0; i < ARRAY_SIZE(instruction); i++) {
    258		msleep(60);
    259		retval = jl2005c_write2(gspca_dev, instruction[i]);
    260		if (retval < 0)
    261			return retval;
    262	}
    263	msleep(60);
    264	return retval;
    265}
    266
    267static int jl2005c_stream_start_cif_small(struct gspca_dev *gspca_dev)
    268{
    269	int i;
    270	int retval = -1;
    271	static u8 instruction[][2] = {
    272		{0x06, 0x00},
    273		{0x7c, 0x00},
    274		{0x7d, 0x32},
    275		{0x02, 0x00},
    276		{0x01, 0x00},
    277		{0x04, 0x42},
    278	};
    279
    280	for (i = 0; i < ARRAY_SIZE(instruction); i++) {
    281		msleep(60);
    282		retval = jl2005c_write2(gspca_dev, instruction[i]);
    283		if (retval < 0)
    284			return retval;
    285	}
    286	msleep(60);
    287	return retval;
    288}
    289
    290
    291static int jl2005c_stop(struct gspca_dev *gspca_dev)
    292{
    293	return jl2005c_write_reg(gspca_dev, 0x07, 0x00);
    294}
    295
    296/*
    297 * This function is called as a workqueue function and runs whenever the camera
    298 * is streaming data. Because it is a workqueue function it is allowed to sleep
    299 * so we can use synchronous USB calls. To avoid possible collisions with other
    300 * threads attempting to use gspca_dev->usb_buf we take the usb_lock when
    301 * performing USB operations using it. In practice we don't really need this
    302 * as the camera doesn't provide any controls.
    303 */
    304static void jl2005c_dostream(struct work_struct *work)
    305{
    306	struct sd *dev = container_of(work, struct sd, work_struct);
    307	struct gspca_dev *gspca_dev = &dev->gspca_dev;
    308	int bytes_left = 0; /* bytes remaining in current frame. */
    309	int data_len;   /* size to use for the next read. */
    310	int header_read = 0;
    311	unsigned char header_sig[2] = {0x4a, 0x4c};
    312	int act_len;
    313	int packet_type;
    314	int ret;
    315	u8 *buffer;
    316
    317	buffer = kmalloc(JL2005C_MAX_TRANSFER, GFP_KERNEL);
    318	if (!buffer) {
    319		pr_err("Couldn't allocate USB buffer\n");
    320		goto quit_stream;
    321	}
    322
    323	while (gspca_dev->present && gspca_dev->streaming) {
    324#ifdef CONFIG_PM
    325		if (gspca_dev->frozen)
    326			break;
    327#endif
    328		/* Check if this is a new frame. If so, start the frame first */
    329		if (!header_read) {
    330			mutex_lock(&gspca_dev->usb_lock);
    331			ret = jl2005c_start_new_frame(gspca_dev);
    332			mutex_unlock(&gspca_dev->usb_lock);
    333			if (ret < 0)
    334				goto quit_stream;
    335			ret = usb_bulk_msg(gspca_dev->dev,
    336				usb_rcvbulkpipe(gspca_dev->dev, 0x82),
    337				buffer, JL2005C_MAX_TRANSFER, &act_len,
    338				JL2005C_DATA_TIMEOUT);
    339			gspca_dbg(gspca_dev, D_PACK,
    340				  "Got %d bytes out of %d for header\n",
    341				  act_len, JL2005C_MAX_TRANSFER);
    342			if (ret < 0 || act_len < JL2005C_MAX_TRANSFER)
    343				goto quit_stream;
    344			/* Check whether we actually got the first blodk */
    345			if (memcmp(header_sig, buffer, 2) != 0) {
    346				pr_err("First block is not the first block\n");
    347				goto quit_stream;
    348			}
    349			/* total size to fetch is byte 7, times blocksize
    350			 * of which we already got act_len */
    351			bytes_left = buffer[0x07] * dev->block_size - act_len;
    352			gspca_dbg(gspca_dev, D_PACK, "bytes_left = 0x%x\n",
    353				  bytes_left);
    354			/* We keep the header. It has other information, too.*/
    355			packet_type = FIRST_PACKET;
    356			gspca_frame_add(gspca_dev, packet_type,
    357					buffer, act_len);
    358			header_read = 1;
    359		}
    360		while (bytes_left > 0 && gspca_dev->present) {
    361			data_len = bytes_left > JL2005C_MAX_TRANSFER ?
    362				JL2005C_MAX_TRANSFER : bytes_left;
    363			ret = usb_bulk_msg(gspca_dev->dev,
    364				usb_rcvbulkpipe(gspca_dev->dev, 0x82),
    365				buffer, data_len, &act_len,
    366				JL2005C_DATA_TIMEOUT);
    367			if (ret < 0 || act_len < data_len)
    368				goto quit_stream;
    369			gspca_dbg(gspca_dev, D_PACK,
    370				  "Got %d bytes out of %d for frame\n",
    371				  data_len, bytes_left);
    372			bytes_left -= data_len;
    373			if (bytes_left == 0) {
    374				packet_type = LAST_PACKET;
    375				header_read = 0;
    376			} else
    377				packet_type = INTER_PACKET;
    378			gspca_frame_add(gspca_dev, packet_type,
    379					buffer, data_len);
    380		}
    381	}
    382quit_stream:
    383	if (gspca_dev->present) {
    384		mutex_lock(&gspca_dev->usb_lock);
    385		jl2005c_stop(gspca_dev);
    386		mutex_unlock(&gspca_dev->usb_lock);
    387	}
    388	kfree(buffer);
    389}
    390
    391
    392
    393
    394/* This function is called at probe time */
    395static int sd_config(struct gspca_dev *gspca_dev,
    396			const struct usb_device_id *id)
    397{
    398	struct cam *cam;
    399	struct sd *sd = (struct sd *) gspca_dev;
    400
    401	cam = &gspca_dev->cam;
    402	/* We don't use the buffer gspca allocates so make it small. */
    403	cam->bulk_size = 64;
    404	cam->bulk = 1;
    405	/* For the rest, the camera needs to be detected */
    406	jl2005c_get_firmware_id(gspca_dev);
    407	/* Here are some known firmware IDs
    408	 * First some JL2005B cameras
    409	 * {0x41, 0x07, 0x04, 0x2c, 0xe8, 0xf2}	Sakar KidzCam
    410	 * {0x45, 0x02, 0x08, 0xb9, 0x00, 0xd2}	No-name JL2005B
    411	 * JL2005C cameras
    412	 * {0x01, 0x0c, 0x16, 0x10, 0xf8, 0xc8}	Argus DC-1512
    413	 * {0x12, 0x04, 0x03, 0xc0, 0x00, 0xd8}	ICarly
    414	 * {0x86, 0x08, 0x05, 0x02, 0x00, 0xd4}	Jazz
    415	 *
    416	 * Based upon this scanty evidence, we can detect a CIF camera by
    417	 * testing byte 0 for 0x4x.
    418	 */
    419	if ((sd->firmware_id[0] & 0xf0) == 0x40) {
    420		cam->cam_mode	= cif_mode;
    421		cam->nmodes	= ARRAY_SIZE(cif_mode);
    422		sd->block_size	= 0x80;
    423	} else {
    424		cam->cam_mode	= vga_mode;
    425		cam->nmodes	= ARRAY_SIZE(vga_mode);
    426		sd->block_size	= 0x200;
    427	}
    428
    429	INIT_WORK(&sd->work_struct, jl2005c_dostream);
    430
    431	return 0;
    432}
    433
    434/* this function is called at probe and resume time */
    435static int sd_init(struct gspca_dev *gspca_dev)
    436{
    437	return 0;
    438}
    439
    440static int sd_start(struct gspca_dev *gspca_dev)
    441{
    442
    443	struct sd *sd = (struct sd *) gspca_dev;
    444	sd->cap_mode = gspca_dev->cam.cam_mode;
    445
    446	switch (gspca_dev->pixfmt.width) {
    447	case 640:
    448		gspca_dbg(gspca_dev, D_STREAM, "Start streaming at vga resolution\n");
    449		jl2005c_stream_start_vga_lg(gspca_dev);
    450		break;
    451	case 320:
    452		gspca_dbg(gspca_dev, D_STREAM, "Start streaming at qvga resolution\n");
    453		jl2005c_stream_start_vga_small(gspca_dev);
    454		break;
    455	case 352:
    456		gspca_dbg(gspca_dev, D_STREAM, "Start streaming at cif resolution\n");
    457		jl2005c_stream_start_cif_lg(gspca_dev);
    458		break;
    459	case 176:
    460		gspca_dbg(gspca_dev, D_STREAM, "Start streaming at qcif resolution\n");
    461		jl2005c_stream_start_cif_small(gspca_dev);
    462		break;
    463	default:
    464		pr_err("Unknown resolution specified\n");
    465		return -1;
    466	}
    467
    468	schedule_work(&sd->work_struct);
    469
    470	return 0;
    471}
    472
    473/* called on streamoff with alt==0 and on disconnect */
    474/* the usb_lock is held at entry - restore on exit */
    475static void sd_stop0(struct gspca_dev *gspca_dev)
    476{
    477	struct sd *dev = (struct sd *) gspca_dev;
    478
    479	/* wait for the work queue to terminate */
    480	mutex_unlock(&gspca_dev->usb_lock);
    481	/* This waits for sq905c_dostream to finish */
    482	flush_work(&dev->work_struct);
    483	mutex_lock(&gspca_dev->usb_lock);
    484}
    485
    486
    487
    488/* sub-driver description */
    489static const struct sd_desc sd_desc = {
    490	.name = MODULE_NAME,
    491	.config = sd_config,
    492	.init = sd_init,
    493	.start = sd_start,
    494	.stop0 = sd_stop0,
    495};
    496
    497/* -- module initialisation -- */
    498static const struct usb_device_id device_table[] = {
    499	{USB_DEVICE(0x0979, 0x0227)},
    500	{}
    501};
    502MODULE_DEVICE_TABLE(usb, device_table);
    503
    504/* -- device connect -- */
    505static int sd_probe(struct usb_interface *intf,
    506				const struct usb_device_id *id)
    507{
    508	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
    509				THIS_MODULE);
    510}
    511
    512static struct usb_driver sd_driver = {
    513	.name = MODULE_NAME,
    514	.id_table = device_table,
    515	.probe = sd_probe,
    516	.disconnect = gspca_disconnect,
    517#ifdef CONFIG_PM
    518	.suspend = gspca_suspend,
    519	.resume = gspca_resume,
    520	.reset_resume = gspca_resume,
    521#endif
    522};
    523
    524module_usb_driver(sd_driver);