0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0017
0018 #define MODULE_NAME "vicam"
0019 #define HEADER_SIZE 64
0020
0021 #include <linux/workqueue.h>
0022 #include <linux/slab.h>
0023 #include <linux/firmware.h>
0024 #include <linux/ihex.h>
0025 #include "gspca.h"
0026
0027 #define VICAM_FIRMWARE "vicam/firmware.fw"
0028
0029 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
0030 MODULE_DESCRIPTION("GSPCA ViCam USB Camera Driver");
0031 MODULE_LICENSE("GPL");
0032 MODULE_FIRMWARE(VICAM_FIRMWARE);
0033
0034 struct sd {
0035 struct gspca_dev gspca_dev;
0036 struct work_struct work_struct;
0037 };
0038
0039
0040
0041
0042 static struct v4l2_pix_format vicam_mode[] = {
0043 { 256, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
0044 .bytesperline = 256,
0045 .sizeimage = 256 * 122,
0046 .colorspace = V4L2_COLORSPACE_SRGB,},
0047
0048 { 256, 200, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
0049 .bytesperline = 256,
0050 .sizeimage = 256 * 200,
0051 .colorspace = V4L2_COLORSPACE_SRGB,},
0052 { 256, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
0053 .bytesperline = 256,
0054 .sizeimage = 256 * 240,
0055 .colorspace = V4L2_COLORSPACE_SRGB,},
0056 #if 0
0057 { 512, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
0058 .bytesperline = 512,
0059 .sizeimage = 512 * 122,
0060 .colorspace = V4L2_COLORSPACE_SRGB,},
0061 #endif
0062 { 512, 244, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
0063 .bytesperline = 512,
0064 .sizeimage = 512 * 244,
0065 .colorspace = V4L2_COLORSPACE_SRGB,},
0066 };
0067
0068 static int vicam_control_msg(struct gspca_dev *gspca_dev, u8 request,
0069 u16 value, u16 index, u8 *data, u16 len)
0070 {
0071 int ret;
0072
0073 ret = usb_control_msg(gspca_dev->dev,
0074 usb_sndctrlpipe(gspca_dev->dev, 0),
0075 request,
0076 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0077 value, index, data, len, 1000);
0078 if (ret < 0)
0079 pr_err("control msg req %02X error %d\n", request, ret);
0080
0081 return ret;
0082 }
0083
0084 static int vicam_set_camera_power(struct gspca_dev *gspca_dev, int state)
0085 {
0086 int ret;
0087
0088 ret = vicam_control_msg(gspca_dev, 0x50, state, 0, NULL, 0);
0089 if (ret < 0)
0090 return ret;
0091
0092 if (state)
0093 ret = vicam_control_msg(gspca_dev, 0x55, 1, 0, NULL, 0);
0094
0095 return ret;
0096 }
0097
0098
0099
0100
0101 static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size)
0102 {
0103 int ret, unscaled_height, act_len = 0;
0104 u8 *req_data = gspca_dev->usb_buf;
0105 s32 expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
0106 s32 gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
0107
0108 memset(req_data, 0, 16);
0109 req_data[0] = gain;
0110 if (gspca_dev->pixfmt.width == 256)
0111 req_data[1] |= 0x01;
0112 if (gspca_dev->pixfmt.height <= 122) {
0113 req_data[1] |= 0x10;
0114 unscaled_height = gspca_dev->pixfmt.height * 2;
0115 } else
0116 unscaled_height = gspca_dev->pixfmt.height;
0117 req_data[2] = 0x90;
0118 if (unscaled_height <= 200)
0119 req_data[3] = 0x06;
0120 else if (unscaled_height <= 242)
0121 req_data[3] = 0x07;
0122 else
0123 req_data[3] = 0x08;
0124
0125 if (expo < 256) {
0126
0127 req_data[4] = 255 - expo;
0128 req_data[5] = 0x00;
0129 req_data[6] = 0x00;
0130 req_data[7] = 0x01;
0131 } else {
0132
0133 req_data[4] = 0x00;
0134 req_data[5] = 0x00;
0135 req_data[6] = expo & 0xFF;
0136 req_data[7] = expo >> 8;
0137 }
0138 req_data[8] = ((244 - unscaled_height) / 2) & ~0x01;
0139
0140
0141 mutex_lock(&gspca_dev->usb_lock);
0142 ret = vicam_control_msg(gspca_dev, 0x51, 0x80, 0, req_data, 16);
0143 mutex_unlock(&gspca_dev->usb_lock);
0144 if (ret < 0)
0145 return ret;
0146
0147 ret = usb_bulk_msg(gspca_dev->dev,
0148 usb_rcvbulkpipe(gspca_dev->dev, 0x81),
0149 data, size, &act_len, 10000);
0150
0151 if (ret < 0 || act_len != size) {
0152 pr_err("bulk read fail (%d) len %d/%d\n",
0153 ret, act_len, size);
0154 return -EIO;
0155 }
0156 return 0;
0157 }
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167 static void vicam_dostream(struct work_struct *work)
0168 {
0169 struct sd *sd = container_of(work, struct sd, work_struct);
0170 struct gspca_dev *gspca_dev = &sd->gspca_dev;
0171 int ret, frame_sz;
0172 u8 *buffer;
0173
0174 frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage +
0175 HEADER_SIZE;
0176 buffer = kmalloc(frame_sz, GFP_KERNEL);
0177 if (!buffer) {
0178 pr_err("Couldn't allocate USB buffer\n");
0179 goto exit;
0180 }
0181
0182 while (gspca_dev->present && gspca_dev->streaming) {
0183 #ifdef CONFIG_PM
0184 if (gspca_dev->frozen)
0185 break;
0186 #endif
0187 ret = vicam_read_frame(gspca_dev, buffer, frame_sz);
0188 if (ret < 0)
0189 break;
0190
0191
0192
0193
0194
0195
0196 gspca_frame_add(gspca_dev, FIRST_PACKET,
0197 buffer + HEADER_SIZE,
0198 frame_sz - HEADER_SIZE);
0199 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
0200 }
0201 exit:
0202 kfree(buffer);
0203 }
0204
0205
0206 static int sd_config(struct gspca_dev *gspca_dev,
0207 const struct usb_device_id *id)
0208 {
0209 struct cam *cam = &gspca_dev->cam;
0210 struct sd *sd = (struct sd *)gspca_dev;
0211
0212
0213 cam->bulk = 1;
0214 cam->bulk_size = 64;
0215 cam->cam_mode = vicam_mode;
0216 cam->nmodes = ARRAY_SIZE(vicam_mode);
0217
0218 INIT_WORK(&sd->work_struct, vicam_dostream);
0219
0220 return 0;
0221 }
0222
0223
0224 static int sd_init(struct gspca_dev *gspca_dev)
0225 {
0226 int ret;
0227 const struct ihex_binrec *rec;
0228 const struct firmware *fw;
0229 u8 *firmware_buf;
0230
0231 ret = request_ihex_firmware(&fw, VICAM_FIRMWARE,
0232 &gspca_dev->dev->dev);
0233 if (ret) {
0234 pr_err("Failed to load \"vicam/firmware.fw\": %d\n", ret);
0235 return ret;
0236 }
0237
0238 firmware_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
0239 if (!firmware_buf) {
0240 ret = -ENOMEM;
0241 goto exit;
0242 }
0243 for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) {
0244 memcpy(firmware_buf, rec->data, be16_to_cpu(rec->len));
0245 ret = vicam_control_msg(gspca_dev, 0xff, 0, 0, firmware_buf,
0246 be16_to_cpu(rec->len));
0247 if (ret < 0)
0248 break;
0249 }
0250
0251 kfree(firmware_buf);
0252 exit:
0253 release_firmware(fw);
0254 return ret;
0255 }
0256
0257
0258 static int sd_start(struct gspca_dev *gspca_dev)
0259 {
0260 struct sd *sd = (struct sd *)gspca_dev;
0261 int ret;
0262
0263 ret = vicam_set_camera_power(gspca_dev, 1);
0264 if (ret < 0)
0265 return ret;
0266
0267 schedule_work(&sd->work_struct);
0268
0269 return 0;
0270 }
0271
0272
0273
0274 static void sd_stop0(struct gspca_dev *gspca_dev)
0275 {
0276 struct sd *dev = (struct sd *)gspca_dev;
0277
0278
0279 mutex_unlock(&gspca_dev->usb_lock);
0280
0281 flush_work(&dev->work_struct);
0282 mutex_lock(&gspca_dev->usb_lock);
0283
0284 if (gspca_dev->present)
0285 vicam_set_camera_power(gspca_dev, 0);
0286 }
0287
0288 static int sd_init_controls(struct gspca_dev *gspca_dev)
0289 {
0290 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
0291
0292 gspca_dev->vdev.ctrl_handler = hdl;
0293 v4l2_ctrl_handler_init(hdl, 2);
0294 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, NULL,
0295 V4L2_CID_EXPOSURE, 0, 2047, 1, 256);
0296 gspca_dev->gain = v4l2_ctrl_new_std(hdl, NULL,
0297 V4L2_CID_GAIN, 0, 255, 1, 200);
0298
0299 if (hdl->error) {
0300 pr_err("Could not initialize controls\n");
0301 return hdl->error;
0302 }
0303 return 0;
0304 }
0305
0306
0307 static const struct usb_device_id device_table[] = {
0308 {USB_DEVICE(0x04c1, 0x009d)},
0309 {USB_DEVICE(0x0602, 0x1001)},
0310 {}
0311 };
0312
0313 MODULE_DEVICE_TABLE(usb, device_table);
0314
0315
0316 static const struct sd_desc sd_desc = {
0317 .name = MODULE_NAME,
0318 .config = sd_config,
0319 .init = sd_init,
0320 .init_controls = sd_init_controls,
0321 .start = sd_start,
0322 .stop0 = sd_stop0,
0323 };
0324
0325
0326 static int sd_probe(struct usb_interface *intf,
0327 const struct usb_device_id *id)
0328 {
0329 return gspca_dev_probe(intf, id,
0330 &sd_desc,
0331 sizeof(struct sd),
0332 THIS_MODULE);
0333 }
0334
0335 static struct usb_driver sd_driver = {
0336 .name = MODULE_NAME,
0337 .id_table = device_table,
0338 .probe = sd_probe,
0339 .disconnect = gspca_disconnect,
0340 #ifdef CONFIG_PM
0341 .suspend = gspca_suspend,
0342 .resume = gspca_resume,
0343 .reset_resume = gspca_resume,
0344 #endif
0345 };
0346
0347 module_usb_driver(sd_driver);