18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * SN9C2028 library 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#define MODULE_NAME "sn9c2028" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "gspca.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ciMODULE_AUTHOR("Theodore Kilgore"); 158c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver"); 168c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/* specific webcam descriptor */ 198c2ecf20Sopenharmony_cistruct sd { 208c2ecf20Sopenharmony_ci struct gspca_dev gspca_dev; /* !! must be the first item */ 218c2ecf20Sopenharmony_ci u8 sof_read; 228c2ecf20Sopenharmony_ci u16 model; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define MIN_AVG_LUM 8500 258c2ecf20Sopenharmony_ci#define MAX_AVG_LUM 10000 268c2ecf20Sopenharmony_ci int avg_lum; 278c2ecf20Sopenharmony_ci u8 avg_lum_l; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci struct { /* autogain and gain control cluster */ 308c2ecf20Sopenharmony_ci struct v4l2_ctrl *autogain; 318c2ecf20Sopenharmony_ci struct v4l2_ctrl *gain; 328c2ecf20Sopenharmony_ci }; 338c2ecf20Sopenharmony_ci}; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistruct init_command { 368c2ecf20Sopenharmony_ci unsigned char instruction[6]; 378c2ecf20Sopenharmony_ci unsigned char to_read; /* length to read. 0 means no reply requested */ 388c2ecf20Sopenharmony_ci}; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* How to change the resolution of any of the VGA cams is unknown */ 418c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format vga_mode[] = { 428c2ecf20Sopenharmony_ci {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE, 438c2ecf20Sopenharmony_ci .bytesperline = 640, 448c2ecf20Sopenharmony_ci .sizeimage = 640 * 480 * 3 / 4, 458c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 468c2ecf20Sopenharmony_ci .priv = 0}, 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* No way to change the resolution of the CIF cams is known */ 508c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format cif_mode[] = { 518c2ecf20Sopenharmony_ci {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE, 528c2ecf20Sopenharmony_ci .bytesperline = 352, 538c2ecf20Sopenharmony_ci .sizeimage = 352 * 288 * 3 / 4, 548c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 558c2ecf20Sopenharmony_ci .priv = 0}, 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* the bytes to write are in gspca_dev->usb_buf */ 598c2ecf20Sopenharmony_cistatic int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci int rc; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "sending command %02x%02x%02x%02x%02x%02x\n", 648c2ecf20Sopenharmony_ci command[0], command[1], command[2], 658c2ecf20Sopenharmony_ci command[3], command[4], command[5]); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci memcpy(gspca_dev->usb_buf, command, 6); 688c2ecf20Sopenharmony_ci rc = usb_control_msg(gspca_dev->dev, 698c2ecf20Sopenharmony_ci usb_sndctrlpipe(gspca_dev->dev, 0), 708c2ecf20Sopenharmony_ci USB_REQ_GET_CONFIGURATION, 718c2ecf20Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 728c2ecf20Sopenharmony_ci 2, 0, gspca_dev->usb_buf, 6, 500); 738c2ecf20Sopenharmony_ci if (rc < 0) { 748c2ecf20Sopenharmony_ci pr_err("command write [%02x] error %d\n", 758c2ecf20Sopenharmony_ci gspca_dev->usb_buf[0], rc); 768c2ecf20Sopenharmony_ci return rc; 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci return 0; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic int sn9c2028_read1(struct gspca_dev *gspca_dev) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci int rc; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci rc = usb_control_msg(gspca_dev->dev, 878c2ecf20Sopenharmony_ci usb_rcvctrlpipe(gspca_dev->dev, 0), 888c2ecf20Sopenharmony_ci USB_REQ_GET_STATUS, 898c2ecf20Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 908c2ecf20Sopenharmony_ci 1, 0, gspca_dev->usb_buf, 1, 500); 918c2ecf20Sopenharmony_ci if (rc != 1) { 928c2ecf20Sopenharmony_ci pr_err("read1 error %d\n", rc); 938c2ecf20Sopenharmony_ci return (rc < 0) ? rc : -EIO; 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "read1 response %02x\n", 968c2ecf20Sopenharmony_ci gspca_dev->usb_buf[0]); 978c2ecf20Sopenharmony_ci return gspca_dev->usb_buf[0]; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci int rc; 1038c2ecf20Sopenharmony_ci rc = usb_control_msg(gspca_dev->dev, 1048c2ecf20Sopenharmony_ci usb_rcvctrlpipe(gspca_dev->dev, 0), 1058c2ecf20Sopenharmony_ci USB_REQ_GET_STATUS, 1068c2ecf20Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 1078c2ecf20Sopenharmony_ci 4, 0, gspca_dev->usb_buf, 4, 500); 1088c2ecf20Sopenharmony_ci if (rc != 4) { 1098c2ecf20Sopenharmony_ci pr_err("read4 error %d\n", rc); 1108c2ecf20Sopenharmony_ci return (rc < 0) ? rc : -EIO; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci memcpy(reading, gspca_dev->usb_buf, 4); 1138c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "read4 response %02x%02x%02x%02x\n", 1148c2ecf20Sopenharmony_ci reading[0], reading[1], reading[2], reading[3]); 1158c2ecf20Sopenharmony_ci return rc; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci int i, status; 1218c2ecf20Sopenharmony_ci __u8 reading[4]; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci status = sn9c2028_command(gspca_dev, command); 1248c2ecf20Sopenharmony_ci if (status < 0) 1258c2ecf20Sopenharmony_ci return status; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci status = -1; 1288c2ecf20Sopenharmony_ci for (i = 0; i < 256 && status < 2; i++) 1298c2ecf20Sopenharmony_ci status = sn9c2028_read1(gspca_dev); 1308c2ecf20Sopenharmony_ci if (status < 0) { 1318c2ecf20Sopenharmony_ci pr_err("long command status read error %d\n", status); 1328c2ecf20Sopenharmony_ci return status; 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci memset(reading, 0, 4); 1368c2ecf20Sopenharmony_ci status = sn9c2028_read4(gspca_dev, reading); 1378c2ecf20Sopenharmony_ci if (status < 0) 1388c2ecf20Sopenharmony_ci return status; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci /* in general, the first byte of the response is the first byte of 1418c2ecf20Sopenharmony_ci * the command, or'ed with 8 */ 1428c2ecf20Sopenharmony_ci status = sn9c2028_read1(gspca_dev); 1438c2ecf20Sopenharmony_ci if (status < 0) 1448c2ecf20Sopenharmony_ci return status; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci return 0; 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci int err_code; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci err_code = sn9c2028_command(gspca_dev, command); 1548c2ecf20Sopenharmony_ci if (err_code < 0) 1558c2ecf20Sopenharmony_ci return err_code; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci err_code = sn9c2028_read1(gspca_dev); 1588c2ecf20Sopenharmony_ci if (err_code < 0) 1598c2ecf20Sopenharmony_ci return err_code; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci return 0; 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci/* this function is called at probe time */ 1658c2ecf20Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev, 1668c2ecf20Sopenharmony_ci const struct usb_device_id *id) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 1698c2ecf20Sopenharmony_ci struct cam *cam = &gspca_dev->cam; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)\n", 1728c2ecf20Sopenharmony_ci id->idVendor, id->idProduct); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci sd->model = id->idProduct; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci switch (sd->model) { 1778c2ecf20Sopenharmony_ci case 0x7005: 1788c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Genius Smart 300 camera\n"); 1798c2ecf20Sopenharmony_ci break; 1808c2ecf20Sopenharmony_ci case 0x7003: 1818c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Genius Videocam Live v2\n"); 1828c2ecf20Sopenharmony_ci break; 1838c2ecf20Sopenharmony_ci case 0x8000: 1848c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "DC31VC\n"); 1858c2ecf20Sopenharmony_ci break; 1868c2ecf20Sopenharmony_ci case 0x8001: 1878c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Spy camera\n"); 1888c2ecf20Sopenharmony_ci break; 1898c2ecf20Sopenharmony_ci case 0x8003: 1908c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "CIF camera\n"); 1918c2ecf20Sopenharmony_ci break; 1928c2ecf20Sopenharmony_ci case 0x8008: 1938c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Mini-Shotz ms-350 camera\n"); 1948c2ecf20Sopenharmony_ci break; 1958c2ecf20Sopenharmony_ci case 0x800a: 1968c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Vivitar 3350b type camera\n"); 1978c2ecf20Sopenharmony_ci cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP; 1988c2ecf20Sopenharmony_ci break; 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci switch (sd->model) { 2028c2ecf20Sopenharmony_ci case 0x8000: 2038c2ecf20Sopenharmony_ci case 0x8001: 2048c2ecf20Sopenharmony_ci case 0x8003: 2058c2ecf20Sopenharmony_ci cam->cam_mode = cif_mode; 2068c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(cif_mode); 2078c2ecf20Sopenharmony_ci break; 2088c2ecf20Sopenharmony_ci default: 2098c2ecf20Sopenharmony_ci cam->cam_mode = vga_mode; 2108c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(vga_mode); 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci return 0; 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci/* this function is called at probe and resume time */ 2168c2ecf20Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci int status; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci sn9c2028_read1(gspca_dev); 2218c2ecf20Sopenharmony_ci sn9c2028_read1(gspca_dev); 2228c2ecf20Sopenharmony_ci status = sn9c2028_read1(gspca_dev); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci return (status < 0) ? status : 0; 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic int run_start_commands(struct gspca_dev *gspca_dev, 2288c2ecf20Sopenharmony_ci struct init_command *cam_commands, int n) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci int i, err_code = -1; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci for (i = 0; i < n; i++) { 2338c2ecf20Sopenharmony_ci switch (cam_commands[i].to_read) { 2348c2ecf20Sopenharmony_ci case 4: 2358c2ecf20Sopenharmony_ci err_code = sn9c2028_long_command(gspca_dev, 2368c2ecf20Sopenharmony_ci cam_commands[i].instruction); 2378c2ecf20Sopenharmony_ci break; 2388c2ecf20Sopenharmony_ci case 1: 2398c2ecf20Sopenharmony_ci err_code = sn9c2028_short_command(gspca_dev, 2408c2ecf20Sopenharmony_ci cam_commands[i].instruction); 2418c2ecf20Sopenharmony_ci break; 2428c2ecf20Sopenharmony_ci case 0: 2438c2ecf20Sopenharmony_ci err_code = sn9c2028_command(gspca_dev, 2448c2ecf20Sopenharmony_ci cam_commands[i].instruction); 2458c2ecf20Sopenharmony_ci break; 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci if (err_code < 0) 2488c2ecf20Sopenharmony_ci return err_code; 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci return 0; 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic void set_gain(struct gspca_dev *gspca_dev, s32 g) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci struct init_command genius_vcam_live_gain_cmds[] = { 2588c2ecf20Sopenharmony_ci {{0x1d, 0x25, 0x10 /* This byte is gain */, 2598c2ecf20Sopenharmony_ci 0x20, 0xab, 0x00}, 0}, 2608c2ecf20Sopenharmony_ci }; 2618c2ecf20Sopenharmony_ci if (!gspca_dev->streaming) 2628c2ecf20Sopenharmony_ci return; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci switch (sd->model) { 2658c2ecf20Sopenharmony_ci case 0x7003: 2668c2ecf20Sopenharmony_ci genius_vcam_live_gain_cmds[0].instruction[2] = g; 2678c2ecf20Sopenharmony_ci run_start_commands(gspca_dev, genius_vcam_live_gain_cmds, 2688c2ecf20Sopenharmony_ci ARRAY_SIZE(genius_vcam_live_gain_cmds)); 2698c2ecf20Sopenharmony_ci break; 2708c2ecf20Sopenharmony_ci default: 2718c2ecf20Sopenharmony_ci break; 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = 2788c2ecf20Sopenharmony_ci container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 2798c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *)gspca_dev; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci gspca_dev->usb_err = 0; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci if (!gspca_dev->streaming) 2848c2ecf20Sopenharmony_ci return 0; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci switch (ctrl->id) { 2878c2ecf20Sopenharmony_ci /* standalone gain control */ 2888c2ecf20Sopenharmony_ci case V4L2_CID_GAIN: 2898c2ecf20Sopenharmony_ci set_gain(gspca_dev, ctrl->val); 2908c2ecf20Sopenharmony_ci break; 2918c2ecf20Sopenharmony_ci /* autogain */ 2928c2ecf20Sopenharmony_ci case V4L2_CID_AUTOGAIN: 2938c2ecf20Sopenharmony_ci set_gain(gspca_dev, sd->gain->val); 2948c2ecf20Sopenharmony_ci break; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci return gspca_dev->usb_err; 2978c2ecf20Sopenharmony_ci} 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops sd_ctrl_ops = { 3008c2ecf20Sopenharmony_ci .s_ctrl = sd_s_ctrl, 3018c2ecf20Sopenharmony_ci}; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic int sd_init_controls(struct gspca_dev *gspca_dev) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 3078c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *)gspca_dev; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci gspca_dev->vdev.ctrl_handler = hdl; 3108c2ecf20Sopenharmony_ci v4l2_ctrl_handler_init(hdl, 2); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci switch (sd->model) { 3138c2ecf20Sopenharmony_ci case 0x7003: 3148c2ecf20Sopenharmony_ci sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 3158c2ecf20Sopenharmony_ci V4L2_CID_GAIN, 0, 20, 1, 0); 3168c2ecf20Sopenharmony_ci sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 3178c2ecf20Sopenharmony_ci V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 3188c2ecf20Sopenharmony_ci break; 3198c2ecf20Sopenharmony_ci default: 3208c2ecf20Sopenharmony_ci break; 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci return 0; 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_cistatic int start_spy_cam(struct gspca_dev *gspca_dev) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci struct init_command spy_start_commands[] = { 3288c2ecf20Sopenharmony_ci {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 3298c2ecf20Sopenharmony_ci {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 3308c2ecf20Sopenharmony_ci {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 3318c2ecf20Sopenharmony_ci {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4}, 3328c2ecf20Sopenharmony_ci {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4}, 3338c2ecf20Sopenharmony_ci {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 3348c2ecf20Sopenharmony_ci {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width 352 */ 3358c2ecf20Sopenharmony_ci {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */ 3368c2ecf20Sopenharmony_ci /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */ 3378c2ecf20Sopenharmony_ci {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, 3388c2ecf20Sopenharmony_ci {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/ 3398c2ecf20Sopenharmony_ci /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */ 3408c2ecf20Sopenharmony_ci {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4}, 3418c2ecf20Sopenharmony_ci /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */ 3428c2ecf20Sopenharmony_ci {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 3438c2ecf20Sopenharmony_ci {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 3448c2ecf20Sopenharmony_ci /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */ 3458c2ecf20Sopenharmony_ci {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 3468c2ecf20Sopenharmony_ci {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, 3478c2ecf20Sopenharmony_ci /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */ 3488c2ecf20Sopenharmony_ci {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, 3498c2ecf20Sopenharmony_ci {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, 3508c2ecf20Sopenharmony_ci {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 3518c2ecf20Sopenharmony_ci {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 3528c2ecf20Sopenharmony_ci {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, 3538c2ecf20Sopenharmony_ci {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4}, 3548c2ecf20Sopenharmony_ci {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/ 3558c2ecf20Sopenharmony_ci /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */ 3568c2ecf20Sopenharmony_ci {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */ 3578c2ecf20Sopenharmony_ci /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */ 3588c2ecf20Sopenharmony_ci {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */ 3598c2ecf20Sopenharmony_ci {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */ 3608c2ecf20Sopenharmony_ci {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4}, 3618c2ecf20Sopenharmony_ci /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */ 3628c2ecf20Sopenharmony_ci {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4}, 3638c2ecf20Sopenharmony_ci {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4}, 3648c2ecf20Sopenharmony_ci {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4}, 3658c2ecf20Sopenharmony_ci {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4}, 3668c2ecf20Sopenharmony_ci {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4}, 3678c2ecf20Sopenharmony_ci {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4}, 3688c2ecf20Sopenharmony_ci {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4}, 3698c2ecf20Sopenharmony_ci /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */ 3708c2ecf20Sopenharmony_ci /* brightness or gain. 0 is default. 4 is good 3718c2ecf20Sopenharmony_ci * indoors at night with incandescent lighting */ 3728c2ecf20Sopenharmony_ci {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4}, 3738c2ecf20Sopenharmony_ci {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/ 3748c2ecf20Sopenharmony_ci {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4}, 3758c2ecf20Sopenharmony_ci {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 3768c2ecf20Sopenharmony_ci {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4}, 3778c2ecf20Sopenharmony_ci {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4}, 3788c2ecf20Sopenharmony_ci /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */ 3798c2ecf20Sopenharmony_ci {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */ 3808c2ecf20Sopenharmony_ci /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */ 3818c2ecf20Sopenharmony_ci {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1}, 3828c2ecf20Sopenharmony_ci {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */ 3838c2ecf20Sopenharmony_ci /* Camera should start to capture now. */ 3848c2ecf20Sopenharmony_ci }; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci return run_start_commands(gspca_dev, spy_start_commands, 3878c2ecf20Sopenharmony_ci ARRAY_SIZE(spy_start_commands)); 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic int start_cif_cam(struct gspca_dev *gspca_dev) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci struct init_command cif_start_commands[] = { 3938c2ecf20Sopenharmony_ci {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 3948c2ecf20Sopenharmony_ci /* The entire sequence below seems redundant */ 3958c2ecf20Sopenharmony_ci /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 3968c2ecf20Sopenharmony_ci {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 3978c2ecf20Sopenharmony_ci {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4}, 3988c2ecf20Sopenharmony_ci {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4}, 3998c2ecf20Sopenharmony_ci {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 4008c2ecf20Sopenharmony_ci {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width? 4018c2ecf20Sopenharmony_ci {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height? 4028c2ecf20Sopenharmony_ci {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample? 4038c2ecf20Sopenharmony_ci {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, 4048c2ecf20Sopenharmony_ci {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4}, 4058c2ecf20Sopenharmony_ci {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 4068c2ecf20Sopenharmony_ci {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 4078c2ecf20Sopenharmony_ci {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 4088c2ecf20Sopenharmony_ci {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 4098c2ecf20Sopenharmony_ci {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 4108c2ecf20Sopenharmony_ci {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 4118c2ecf20Sopenharmony_ci {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 4128c2ecf20Sopenharmony_ci {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 4138c2ecf20Sopenharmony_ci {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/ 4148c2ecf20Sopenharmony_ci {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1}, 4158c2ecf20Sopenharmony_ci {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1}, 4168c2ecf20Sopenharmony_ci {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1}, 4178c2ecf20Sopenharmony_ci {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, 4188c2ecf20Sopenharmony_ci {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1}, 4198c2ecf20Sopenharmony_ci {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1}, 4208c2ecf20Sopenharmony_ci {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1}, 4218c2ecf20Sopenharmony_ci {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1}, 4228c2ecf20Sopenharmony_ci {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1}, 4238c2ecf20Sopenharmony_ci {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1}, 4248c2ecf20Sopenharmony_ci {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1}, 4258c2ecf20Sopenharmony_ci {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1}, 4268c2ecf20Sopenharmony_ci {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1}, 4278c2ecf20Sopenharmony_ci {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1}, 4288c2ecf20Sopenharmony_ci {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1}, 4298c2ecf20Sopenharmony_ci {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1}, 4308c2ecf20Sopenharmony_ci {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1}, 4318c2ecf20Sopenharmony_ci {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1}, 4328c2ecf20Sopenharmony_ci {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1}, 4338c2ecf20Sopenharmony_ci {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1}, 4348c2ecf20Sopenharmony_ci {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1}, 4358c2ecf20Sopenharmony_ci {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, 4368c2ecf20Sopenharmony_ci {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */ 4378c2ecf20Sopenharmony_ci {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */ 4388c2ecf20Sopenharmony_ci /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample? 4398c2ecf20Sopenharmony_ci * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing 4408c2ecf20Sopenharmony_ci * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */ 4418c2ecf20Sopenharmony_ci /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, 4428c2ecf20Sopenharmony_ci * causes subsampling 4438c2ecf20Sopenharmony_ci * but not a change in the resolution setting! */ 4448c2ecf20Sopenharmony_ci {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 4458c2ecf20Sopenharmony_ci {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4}, 4468c2ecf20Sopenharmony_ci {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4}, 4478c2ecf20Sopenharmony_ci {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4}, 4488c2ecf20Sopenharmony_ci {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, 4498c2ecf20Sopenharmony_ci {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1}, 4508c2ecf20Sopenharmony_ci {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1}, 4518c2ecf20Sopenharmony_ci {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1}, 4528c2ecf20Sopenharmony_ci {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1}, 4538c2ecf20Sopenharmony_ci {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, 4548c2ecf20Sopenharmony_ci {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1}, 4558c2ecf20Sopenharmony_ci {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1}, 4568c2ecf20Sopenharmony_ci {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1}, 4578c2ecf20Sopenharmony_ci {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, 4588c2ecf20Sopenharmony_ci {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, 4598c2ecf20Sopenharmony_ci {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */ 4608c2ecf20Sopenharmony_ci /* Camera should start to capture now. */ 4618c2ecf20Sopenharmony_ci }; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci return run_start_commands(gspca_dev, cif_start_commands, 4648c2ecf20Sopenharmony_ci ARRAY_SIZE(cif_start_commands)); 4658c2ecf20Sopenharmony_ci} 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_cistatic int start_ms350_cam(struct gspca_dev *gspca_dev) 4688c2ecf20Sopenharmony_ci{ 4698c2ecf20Sopenharmony_ci struct init_command ms350_start_commands[] = { 4708c2ecf20Sopenharmony_ci {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 4718c2ecf20Sopenharmony_ci {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 4728c2ecf20Sopenharmony_ci {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 4738c2ecf20Sopenharmony_ci {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 4748c2ecf20Sopenharmony_ci {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4}, 4758c2ecf20Sopenharmony_ci {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4}, 4768c2ecf20Sopenharmony_ci {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 4778c2ecf20Sopenharmony_ci {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, 4788c2ecf20Sopenharmony_ci {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, 4798c2ecf20Sopenharmony_ci {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, 4808c2ecf20Sopenharmony_ci {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, 4818c2ecf20Sopenharmony_ci {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4}, 4828c2ecf20Sopenharmony_ci {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 4838c2ecf20Sopenharmony_ci {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 4848c2ecf20Sopenharmony_ci {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 4858c2ecf20Sopenharmony_ci {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 4868c2ecf20Sopenharmony_ci {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 4878c2ecf20Sopenharmony_ci {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 4888c2ecf20Sopenharmony_ci {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 4898c2ecf20Sopenharmony_ci {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 4908c2ecf20Sopenharmony_ci {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, 4918c2ecf20Sopenharmony_ci {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4}, 4928c2ecf20Sopenharmony_ci {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4}, 4938c2ecf20Sopenharmony_ci {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4}, 4948c2ecf20Sopenharmony_ci {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4}, 4958c2ecf20Sopenharmony_ci {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4}, 4968c2ecf20Sopenharmony_ci {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4}, 4978c2ecf20Sopenharmony_ci {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4}, 4988c2ecf20Sopenharmony_ci {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4}, 4998c2ecf20Sopenharmony_ci {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4}, 5008c2ecf20Sopenharmony_ci {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4}, 5018c2ecf20Sopenharmony_ci {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4}, 5028c2ecf20Sopenharmony_ci {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4}, 5038c2ecf20Sopenharmony_ci {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4}, 5048c2ecf20Sopenharmony_ci {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4}, 5058c2ecf20Sopenharmony_ci {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4}, 5068c2ecf20Sopenharmony_ci {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, 5078c2ecf20Sopenharmony_ci {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 5088c2ecf20Sopenharmony_ci {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4}, 5098c2ecf20Sopenharmony_ci {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 5108c2ecf20Sopenharmony_ci {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4}, 5118c2ecf20Sopenharmony_ci {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4}, 5128c2ecf20Sopenharmony_ci {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4}, 5138c2ecf20Sopenharmony_ci {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4}, 5148c2ecf20Sopenharmony_ci {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width */ 5158c2ecf20Sopenharmony_ci {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */ 5168c2ecf20Sopenharmony_ci {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */ 5178c2ecf20Sopenharmony_ci {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, 5188c2ecf20Sopenharmony_ci {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */ 5198c2ecf20Sopenharmony_ci {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 5208c2ecf20Sopenharmony_ci {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 5218c2ecf20Sopenharmony_ci {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 5228c2ecf20Sopenharmony_ci {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 5238c2ecf20Sopenharmony_ci {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1}, 5248c2ecf20Sopenharmony_ci {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, 5258c2ecf20Sopenharmony_ci {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1}, 5268c2ecf20Sopenharmony_ci {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1}, 5278c2ecf20Sopenharmony_ci {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0}, 5288c2ecf20Sopenharmony_ci /* Camera should start to capture now. */ 5298c2ecf20Sopenharmony_ci }; 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci return run_start_commands(gspca_dev, ms350_start_commands, 5328c2ecf20Sopenharmony_ci ARRAY_SIZE(ms350_start_commands)); 5338c2ecf20Sopenharmony_ci} 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_cistatic int start_genius_cam(struct gspca_dev *gspca_dev) 5368c2ecf20Sopenharmony_ci{ 5378c2ecf20Sopenharmony_ci struct init_command genius_start_commands[] = { 5388c2ecf20Sopenharmony_ci {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 5398c2ecf20Sopenharmony_ci {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 5408c2ecf20Sopenharmony_ci {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4}, 5418c2ecf20Sopenharmony_ci {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, 5428c2ecf20Sopenharmony_ci {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, 5438c2ecf20Sopenharmony_ci /* "preliminary" width and height settings */ 5448c2ecf20Sopenharmony_ci {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 5458c2ecf20Sopenharmony_ci {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 5468c2ecf20Sopenharmony_ci {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, 5478c2ecf20Sopenharmony_ci {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 5488c2ecf20Sopenharmony_ci {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, 5498c2ecf20Sopenharmony_ci {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, 5508c2ecf20Sopenharmony_ci {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, 5518c2ecf20Sopenharmony_ci {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 5528c2ecf20Sopenharmony_ci {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, 5538c2ecf20Sopenharmony_ci {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 5548c2ecf20Sopenharmony_ci {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, 5558c2ecf20Sopenharmony_ci {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 5568c2ecf20Sopenharmony_ci {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4}, 5578c2ecf20Sopenharmony_ci {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 5588c2ecf20Sopenharmony_ci {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4}, 5598c2ecf20Sopenharmony_ci {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 5608c2ecf20Sopenharmony_ci {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4}, 5618c2ecf20Sopenharmony_ci {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4}, 5628c2ecf20Sopenharmony_ci {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4}, 5638c2ecf20Sopenharmony_ci {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 5648c2ecf20Sopenharmony_ci {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, 5658c2ecf20Sopenharmony_ci {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 5668c2ecf20Sopenharmony_ci {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, 5678c2ecf20Sopenharmony_ci {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4}, 5688c2ecf20Sopenharmony_ci {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4}, 5698c2ecf20Sopenharmony_ci {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4}, 5708c2ecf20Sopenharmony_ci {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4}, 5718c2ecf20Sopenharmony_ci {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4}, 5728c2ecf20Sopenharmony_ci {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4}, 5738c2ecf20Sopenharmony_ci {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4}, 5748c2ecf20Sopenharmony_ci {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4}, 5758c2ecf20Sopenharmony_ci {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4}, 5768c2ecf20Sopenharmony_ci {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */ 5778c2ecf20Sopenharmony_ci {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */ 5788c2ecf20Sopenharmony_ci {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 5798c2ecf20Sopenharmony_ci {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 5808c2ecf20Sopenharmony_ci {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4}, 5818c2ecf20Sopenharmony_ci {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 5828c2ecf20Sopenharmony_ci {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 5838c2ecf20Sopenharmony_ci {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 5848c2ecf20Sopenharmony_ci {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 5858c2ecf20Sopenharmony_ci {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 5868c2ecf20Sopenharmony_ci {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4}, 5878c2ecf20Sopenharmony_ci {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 5888c2ecf20Sopenharmony_ci {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4}, 5898c2ecf20Sopenharmony_ci {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 5908c2ecf20Sopenharmony_ci {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4}, 5918c2ecf20Sopenharmony_ci {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 5928c2ecf20Sopenharmony_ci {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4}, 5938c2ecf20Sopenharmony_ci {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 5948c2ecf20Sopenharmony_ci {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4}, 5958c2ecf20Sopenharmony_ci {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4}, 5968c2ecf20Sopenharmony_ci {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4}, 5978c2ecf20Sopenharmony_ci {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, 5988c2ecf20Sopenharmony_ci {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, 5998c2ecf20Sopenharmony_ci {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0} 6008c2ecf20Sopenharmony_ci /* Camera should start to capture now. */ 6018c2ecf20Sopenharmony_ci }; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci return run_start_commands(gspca_dev, genius_start_commands, 6048c2ecf20Sopenharmony_ci ARRAY_SIZE(genius_start_commands)); 6058c2ecf20Sopenharmony_ci} 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_cistatic int start_genius_videocam_live(struct gspca_dev *gspca_dev) 6088c2ecf20Sopenharmony_ci{ 6098c2ecf20Sopenharmony_ci int r; 6108c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 6118c2ecf20Sopenharmony_ci struct init_command genius_vcam_live_start_commands[] = { 6128c2ecf20Sopenharmony_ci {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 0}, 6138c2ecf20Sopenharmony_ci {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 6148c2ecf20Sopenharmony_ci {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4}, 6158c2ecf20Sopenharmony_ci {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, 6168c2ecf20Sopenharmony_ci {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 6198c2ecf20Sopenharmony_ci {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 6208c2ecf20Sopenharmony_ci {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, 6218c2ecf20Sopenharmony_ci {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 6228c2ecf20Sopenharmony_ci {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, 6238c2ecf20Sopenharmony_ci {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, 6248c2ecf20Sopenharmony_ci {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, 6258c2ecf20Sopenharmony_ci {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 6268c2ecf20Sopenharmony_ci {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, 6278c2ecf20Sopenharmony_ci {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 6288c2ecf20Sopenharmony_ci {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, 6298c2ecf20Sopenharmony_ci {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 6308c2ecf20Sopenharmony_ci {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4}, 6318c2ecf20Sopenharmony_ci {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 6328c2ecf20Sopenharmony_ci {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4}, 6338c2ecf20Sopenharmony_ci {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 6348c2ecf20Sopenharmony_ci {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4}, 6358c2ecf20Sopenharmony_ci {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4}, 6368c2ecf20Sopenharmony_ci {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4}, 6378c2ecf20Sopenharmony_ci {{0x1c, 0x20, 0x00, 0x2d, 0x00, 0x00}, 4}, 6388c2ecf20Sopenharmony_ci {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 6398c2ecf20Sopenharmony_ci {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 6408c2ecf20Sopenharmony_ci {{0x13, 0x22, 0x01, 0x00, 0x00, 0x00}, 4}, 6418c2ecf20Sopenharmony_ci {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4}, 6428c2ecf20Sopenharmony_ci {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 6438c2ecf20Sopenharmony_ci {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, 6448c2ecf20Sopenharmony_ci {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, 6458c2ecf20Sopenharmony_ci {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 6468c2ecf20Sopenharmony_ci {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 6478c2ecf20Sopenharmony_ci {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, 6488c2ecf20Sopenharmony_ci {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 6498c2ecf20Sopenharmony_ci {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 6508c2ecf20Sopenharmony_ci {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 6518c2ecf20Sopenharmony_ci {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, 6528c2ecf20Sopenharmony_ci {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, 6538c2ecf20Sopenharmony_ci {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, 6548c2ecf20Sopenharmony_ci {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 6558c2ecf20Sopenharmony_ci {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 6568c2ecf20Sopenharmony_ci {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, 6578c2ecf20Sopenharmony_ci {{0x11, 0x01, 0x04, 0x00, 0x00, 0x00}, 4}, 6588c2ecf20Sopenharmony_ci {{0x11, 0x02, 0x92, 0x00, 0x00, 0x00}, 4}, 6598c2ecf20Sopenharmony_ci {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 6608c2ecf20Sopenharmony_ci {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4}, 6618c2ecf20Sopenharmony_ci {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 6628c2ecf20Sopenharmony_ci {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4}, 6638c2ecf20Sopenharmony_ci {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 6648c2ecf20Sopenharmony_ci {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4}, 6658c2ecf20Sopenharmony_ci {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4}, 6668c2ecf20Sopenharmony_ci {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4}, 6678c2ecf20Sopenharmony_ci {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 6688c2ecf20Sopenharmony_ci {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, 6698c2ecf20Sopenharmony_ci {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 6708c2ecf20Sopenharmony_ci {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, 6718c2ecf20Sopenharmony_ci {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4}, 6728c2ecf20Sopenharmony_ci {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4}, 6738c2ecf20Sopenharmony_ci {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4}, 6748c2ecf20Sopenharmony_ci {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4}, 6758c2ecf20Sopenharmony_ci {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4}, 6768c2ecf20Sopenharmony_ci {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4}, 6778c2ecf20Sopenharmony_ci {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4}, 6788c2ecf20Sopenharmony_ci {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4}, 6798c2ecf20Sopenharmony_ci {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4}, 6808c2ecf20Sopenharmony_ci {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, 6818c2ecf20Sopenharmony_ci {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, 6828c2ecf20Sopenharmony_ci {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 6838c2ecf20Sopenharmony_ci {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 6848c2ecf20Sopenharmony_ci {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4}, 6858c2ecf20Sopenharmony_ci {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 6868c2ecf20Sopenharmony_ci {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 6878c2ecf20Sopenharmony_ci {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 6888c2ecf20Sopenharmony_ci {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 6898c2ecf20Sopenharmony_ci {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 6908c2ecf20Sopenharmony_ci {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4}, 6918c2ecf20Sopenharmony_ci {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 6928c2ecf20Sopenharmony_ci {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4}, 6938c2ecf20Sopenharmony_ci {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 6948c2ecf20Sopenharmony_ci {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4}, 6958c2ecf20Sopenharmony_ci {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 6968c2ecf20Sopenharmony_ci {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4}, 6978c2ecf20Sopenharmony_ci {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 6988c2ecf20Sopenharmony_ci {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4}, 6998c2ecf20Sopenharmony_ci {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4}, 7008c2ecf20Sopenharmony_ci {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4}, 7018c2ecf20Sopenharmony_ci {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, 7028c2ecf20Sopenharmony_ci {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0}, 7038c2ecf20Sopenharmony_ci /* Camera should start to capture now. */ 7048c2ecf20Sopenharmony_ci {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 0}, 7058c2ecf20Sopenharmony_ci {{0x1b, 0x32, 0x26, 0x00, 0x00, 0x00}, 0}, 7068c2ecf20Sopenharmony_ci {{0x1d, 0x25, 0x10, 0x20, 0xab, 0x00}, 0}, 7078c2ecf20Sopenharmony_ci }; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci r = run_start_commands(gspca_dev, genius_vcam_live_start_commands, 7108c2ecf20Sopenharmony_ci ARRAY_SIZE(genius_vcam_live_start_commands)); 7118c2ecf20Sopenharmony_ci if (r < 0) 7128c2ecf20Sopenharmony_ci return r; 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci if (sd->gain) 7158c2ecf20Sopenharmony_ci set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain)); 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci return r; 7188c2ecf20Sopenharmony_ci} 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_cistatic int start_vivitar_cam(struct gspca_dev *gspca_dev) 7218c2ecf20Sopenharmony_ci{ 7228c2ecf20Sopenharmony_ci struct init_command vivitar_start_commands[] = { 7238c2ecf20Sopenharmony_ci {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 7248c2ecf20Sopenharmony_ci {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 7258c2ecf20Sopenharmony_ci {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 7268c2ecf20Sopenharmony_ci {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4}, 7278c2ecf20Sopenharmony_ci {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4}, 7288c2ecf20Sopenharmony_ci {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 7298c2ecf20Sopenharmony_ci {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, 7308c2ecf20Sopenharmony_ci {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, 7318c2ecf20Sopenharmony_ci {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 7328c2ecf20Sopenharmony_ci {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4}, 7338c2ecf20Sopenharmony_ci /* 7348c2ecf20Sopenharmony_ci * Above is changed from OEM 0x0b. Fixes Bayer tiling. 7358c2ecf20Sopenharmony_ci * Presumably gives a vertical shift of one row. 7368c2ecf20Sopenharmony_ci */ 7378c2ecf20Sopenharmony_ci {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4}, 7388c2ecf20Sopenharmony_ci /* Above seems to do horizontal shift. */ 7398c2ecf20Sopenharmony_ci {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 7408c2ecf20Sopenharmony_ci {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 7418c2ecf20Sopenharmony_ci {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 7428c2ecf20Sopenharmony_ci {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 7438c2ecf20Sopenharmony_ci {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 7448c2ecf20Sopenharmony_ci {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 7458c2ecf20Sopenharmony_ci /* Above three commands seem to relate to brightness. */ 7468c2ecf20Sopenharmony_ci {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 7478c2ecf20Sopenharmony_ci {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 7488c2ecf20Sopenharmony_ci {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, 7498c2ecf20Sopenharmony_ci {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1}, 7508c2ecf20Sopenharmony_ci {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1}, 7518c2ecf20Sopenharmony_ci {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1}, 7528c2ecf20Sopenharmony_ci {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1}, 7538c2ecf20Sopenharmony_ci {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1}, 7548c2ecf20Sopenharmony_ci {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1}, 7558c2ecf20Sopenharmony_ci {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1}, 7568c2ecf20Sopenharmony_ci {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1}, 7578c2ecf20Sopenharmony_ci {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1}, 7588c2ecf20Sopenharmony_ci {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1}, 7598c2ecf20Sopenharmony_ci {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1}, 7608c2ecf20Sopenharmony_ci {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1}, 7618c2ecf20Sopenharmony_ci {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1}, 7628c2ecf20Sopenharmony_ci {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1}, 7638c2ecf20Sopenharmony_ci {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1}, 7648c2ecf20Sopenharmony_ci {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1}, 7658c2ecf20Sopenharmony_ci {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1}, 7668c2ecf20Sopenharmony_ci {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1}, 7678c2ecf20Sopenharmony_ci {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1}, 7688c2ecf20Sopenharmony_ci {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1}, 7698c2ecf20Sopenharmony_ci {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1}, 7708c2ecf20Sopenharmony_ci {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1}, 7718c2ecf20Sopenharmony_ci {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1}, 7728c2ecf20Sopenharmony_ci {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1}, 7738c2ecf20Sopenharmony_ci {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1}, 7748c2ecf20Sopenharmony_ci {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1}, 7758c2ecf20Sopenharmony_ci {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1}, 7768c2ecf20Sopenharmony_ci {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1}, 7778c2ecf20Sopenharmony_ci {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1}, 7788c2ecf20Sopenharmony_ci {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1}, 7798c2ecf20Sopenharmony_ci {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1}, 7808c2ecf20Sopenharmony_ci {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1}, 7818c2ecf20Sopenharmony_ci {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1}, 7828c2ecf20Sopenharmony_ci {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1}, 7838c2ecf20Sopenharmony_ci /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, 7848c2ecf20Sopenharmony_ci {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, 7858c2ecf20Sopenharmony_ci {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */ 7868c2ecf20Sopenharmony_ci {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1}, 7878c2ecf20Sopenharmony_ci {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1}, 7888c2ecf20Sopenharmony_ci {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, 7898c2ecf20Sopenharmony_ci {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1}, 7908c2ecf20Sopenharmony_ci {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1}, 7918c2ecf20Sopenharmony_ci {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1}, 7928c2ecf20Sopenharmony_ci /* Above is brightness; OEM driver setting is 0x10 */ 7938c2ecf20Sopenharmony_ci {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, 7948c2ecf20Sopenharmony_ci {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1}, 7958c2ecf20Sopenharmony_ci {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1} 7968c2ecf20Sopenharmony_ci }; 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci return run_start_commands(gspca_dev, vivitar_start_commands, 7998c2ecf20Sopenharmony_ci ARRAY_SIZE(vivitar_start_commands)); 8008c2ecf20Sopenharmony_ci} 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev) 8038c2ecf20Sopenharmony_ci{ 8048c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 8058c2ecf20Sopenharmony_ci int err_code; 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci sd->sof_read = 0; 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci switch (sd->model) { 8108c2ecf20Sopenharmony_ci case 0x7005: 8118c2ecf20Sopenharmony_ci err_code = start_genius_cam(gspca_dev); 8128c2ecf20Sopenharmony_ci break; 8138c2ecf20Sopenharmony_ci case 0x7003: 8148c2ecf20Sopenharmony_ci err_code = start_genius_videocam_live(gspca_dev); 8158c2ecf20Sopenharmony_ci break; 8168c2ecf20Sopenharmony_ci case 0x8001: 8178c2ecf20Sopenharmony_ci err_code = start_spy_cam(gspca_dev); 8188c2ecf20Sopenharmony_ci break; 8198c2ecf20Sopenharmony_ci case 0x8003: 8208c2ecf20Sopenharmony_ci err_code = start_cif_cam(gspca_dev); 8218c2ecf20Sopenharmony_ci break; 8228c2ecf20Sopenharmony_ci case 0x8008: 8238c2ecf20Sopenharmony_ci err_code = start_ms350_cam(gspca_dev); 8248c2ecf20Sopenharmony_ci break; 8258c2ecf20Sopenharmony_ci case 0x800a: 8268c2ecf20Sopenharmony_ci err_code = start_vivitar_cam(gspca_dev); 8278c2ecf20Sopenharmony_ci break; 8288c2ecf20Sopenharmony_ci default: 8298c2ecf20Sopenharmony_ci pr_err("Starting unknown camera, please report this\n"); 8308c2ecf20Sopenharmony_ci return -ENXIO; 8318c2ecf20Sopenharmony_ci } 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci sd->avg_lum = -1; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci return err_code; 8368c2ecf20Sopenharmony_ci} 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_cistatic void sd_stopN(struct gspca_dev *gspca_dev) 8398c2ecf20Sopenharmony_ci{ 8408c2ecf20Sopenharmony_ci int result; 8418c2ecf20Sopenharmony_ci __u8 data[6]; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci result = sn9c2028_read1(gspca_dev); 8448c2ecf20Sopenharmony_ci if (result < 0) 8458c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Camera Stop read failed\n"); 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci memset(data, 0, 6); 8488c2ecf20Sopenharmony_ci data[0] = 0x14; 8498c2ecf20Sopenharmony_ci result = sn9c2028_command(gspca_dev, data); 8508c2ecf20Sopenharmony_ci if (result < 0) 8518c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Camera Stop command failed\n"); 8528c2ecf20Sopenharmony_ci} 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_cistatic void do_autogain(struct gspca_dev *gspca_dev, int avg_lum) 8558c2ecf20Sopenharmony_ci{ 8568c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 8578c2ecf20Sopenharmony_ci s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain); 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci if (avg_lum == -1) 8608c2ecf20Sopenharmony_ci return; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci if (avg_lum < MIN_AVG_LUM) { 8638c2ecf20Sopenharmony_ci if (cur_gain == sd->gain->maximum) 8648c2ecf20Sopenharmony_ci return; 8658c2ecf20Sopenharmony_ci cur_gain++; 8668c2ecf20Sopenharmony_ci v4l2_ctrl_s_ctrl(sd->gain, cur_gain); 8678c2ecf20Sopenharmony_ci } 8688c2ecf20Sopenharmony_ci if (avg_lum > MAX_AVG_LUM) { 8698c2ecf20Sopenharmony_ci if (cur_gain == sd->gain->minimum) 8708c2ecf20Sopenharmony_ci return; 8718c2ecf20Sopenharmony_ci cur_gain--; 8728c2ecf20Sopenharmony_ci v4l2_ctrl_s_ctrl(sd->gain, cur_gain); 8738c2ecf20Sopenharmony_ci } 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci} 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_cistatic void sd_dqcallback(struct gspca_dev *gspca_dev) 8788c2ecf20Sopenharmony_ci{ 8798c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain)) 8828c2ecf20Sopenharmony_ci return; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci do_autogain(gspca_dev, sd->avg_lum); 8858c2ecf20Sopenharmony_ci} 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci/* Include sn9c2028 sof detection functions */ 8888c2ecf20Sopenharmony_ci#include "sn9c2028.h" 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_cistatic void sd_pkt_scan(struct gspca_dev *gspca_dev, 8918c2ecf20Sopenharmony_ci __u8 *data, /* isoc packet */ 8928c2ecf20Sopenharmony_ci int len) /* iso packet length */ 8938c2ecf20Sopenharmony_ci{ 8948c2ecf20Sopenharmony_ci unsigned char *sof; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci sof = sn9c2028_find_sof(gspca_dev, data, len); 8978c2ecf20Sopenharmony_ci if (sof) { 8988c2ecf20Sopenharmony_ci int n; 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci /* finish decoding current frame */ 9018c2ecf20Sopenharmony_ci n = sof - data; 9028c2ecf20Sopenharmony_ci if (n > sizeof sn9c2028_sof_marker) 9038c2ecf20Sopenharmony_ci n -= sizeof sn9c2028_sof_marker; 9048c2ecf20Sopenharmony_ci else 9058c2ecf20Sopenharmony_ci n = 0; 9068c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, LAST_PACKET, data, n); 9078c2ecf20Sopenharmony_ci /* Start next frame. */ 9088c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, 9098c2ecf20Sopenharmony_ci sn9c2028_sof_marker, sizeof sn9c2028_sof_marker); 9108c2ecf20Sopenharmony_ci len -= sof - data; 9118c2ecf20Sopenharmony_ci data = sof; 9128c2ecf20Sopenharmony_ci } 9138c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 9148c2ecf20Sopenharmony_ci} 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci/* sub-driver description */ 9178c2ecf20Sopenharmony_cistatic const struct sd_desc sd_desc = { 9188c2ecf20Sopenharmony_ci .name = MODULE_NAME, 9198c2ecf20Sopenharmony_ci .config = sd_config, 9208c2ecf20Sopenharmony_ci .init = sd_init, 9218c2ecf20Sopenharmony_ci .init_controls = sd_init_controls, 9228c2ecf20Sopenharmony_ci .start = sd_start, 9238c2ecf20Sopenharmony_ci .stopN = sd_stopN, 9248c2ecf20Sopenharmony_ci .dq_callback = sd_dqcallback, 9258c2ecf20Sopenharmony_ci .pkt_scan = sd_pkt_scan, 9268c2ecf20Sopenharmony_ci}; 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci/* -- module initialisation -- */ 9298c2ecf20Sopenharmony_cistatic const struct usb_device_id device_table[] = { 9308c2ecf20Sopenharmony_ci {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */ 9318c2ecf20Sopenharmony_ci {USB_DEVICE(0x0458, 0x7003)}, /* Genius Videocam Live v2 */ 9328c2ecf20Sopenharmony_ci /* The Genius Smart is untested. I can't find an owner ! */ 9338c2ecf20Sopenharmony_ci /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */ 9348c2ecf20Sopenharmony_ci {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */ 9358c2ecf20Sopenharmony_ci {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */ 9368c2ecf20Sopenharmony_ci /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */ 9378c2ecf20Sopenharmony_ci {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */ 9388c2ecf20Sopenharmony_ci {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */ 9398c2ecf20Sopenharmony_ci {} 9408c2ecf20Sopenharmony_ci}; 9418c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table); 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci/* -- device connect -- */ 9448c2ecf20Sopenharmony_cistatic int sd_probe(struct usb_interface *intf, 9458c2ecf20Sopenharmony_ci const struct usb_device_id *id) 9468c2ecf20Sopenharmony_ci{ 9478c2ecf20Sopenharmony_ci return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 9488c2ecf20Sopenharmony_ci THIS_MODULE); 9498c2ecf20Sopenharmony_ci} 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_cistatic struct usb_driver sd_driver = { 9528c2ecf20Sopenharmony_ci .name = MODULE_NAME, 9538c2ecf20Sopenharmony_ci .id_table = device_table, 9548c2ecf20Sopenharmony_ci .probe = sd_probe, 9558c2ecf20Sopenharmony_ci .disconnect = gspca_disconnect, 9568c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 9578c2ecf20Sopenharmony_ci .suspend = gspca_suspend, 9588c2ecf20Sopenharmony_ci .resume = gspca_resume, 9598c2ecf20Sopenharmony_ci .reset_resume = gspca_resume, 9608c2ecf20Sopenharmony_ci#endif 9618c2ecf20Sopenharmony_ci}; 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_cimodule_usb_driver(sd_driver); 964