1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#define MODULE_NAME "vicam"
30#define HEADER_SIZE 64
31
32#include <linux/workqueue.h>
33#include <linux/slab.h>
34#include <linux/firmware.h>
35#include <linux/ihex.h>
36#include "gspca.h"
37
38MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
39MODULE_DESCRIPTION("GSPCA ViCam USB Camera Driver");
40MODULE_LICENSE("GPL");
41
42enum e_ctrl {
43 GAIN,
44 EXPOSURE,
45 NCTRL
46};
47
48struct sd {
49 struct gspca_dev gspca_dev;
50 struct work_struct work_struct;
51 struct workqueue_struct *work_thread;
52 struct gspca_ctrl ctrls[NCTRL];
53};
54
55
56
57
58static struct v4l2_pix_format vicam_mode[] = {
59 { 256, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
60 .bytesperline = 256,
61 .sizeimage = 256 * 122,
62 .colorspace = V4L2_COLORSPACE_SRGB,},
63
64 { 256, 200, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
65 .bytesperline = 256,
66 .sizeimage = 256 * 200,
67 .colorspace = V4L2_COLORSPACE_SRGB,},
68 { 256, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
69 .bytesperline = 256,
70 .sizeimage = 256 * 240,
71 .colorspace = V4L2_COLORSPACE_SRGB,},
72#if 0
73 { 512, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
74 .bytesperline = 512,
75 .sizeimage = 512 * 122,
76 .colorspace = V4L2_COLORSPACE_SRGB,},
77#endif
78 { 512, 244, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
79 .bytesperline = 512,
80 .sizeimage = 512 * 244,
81 .colorspace = V4L2_COLORSPACE_SRGB,},
82};
83
84static const struct ctrl sd_ctrls[] = {
85[GAIN] = {
86 {
87 .id = V4L2_CID_GAIN,
88 .type = V4L2_CTRL_TYPE_INTEGER,
89 .name = "Gain",
90 .minimum = 0,
91 .maximum = 255,
92 .step = 1,
93 .default_value = 200,
94 },
95 },
96[EXPOSURE] = {
97 {
98 .id = V4L2_CID_EXPOSURE,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Exposure",
101 .minimum = 0,
102 .maximum = 2047,
103 .step = 1,
104 .default_value = 256,
105 },
106 },
107};
108
109static int vicam_control_msg(struct gspca_dev *gspca_dev, u8 request,
110 u16 value, u16 index, u8 *data, u16 len)
111{
112 int ret;
113
114 ret = usb_control_msg(gspca_dev->dev,
115 usb_sndctrlpipe(gspca_dev->dev, 0),
116 request,
117 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
118 value, index, data, len, 1000);
119 if (ret < 0)
120 err("control msg req %02X error %d", request, ret);
121
122 return ret;
123}
124
125static int vicam_set_camera_power(struct gspca_dev *gspca_dev, int state)
126{
127 int ret;
128
129 ret = vicam_control_msg(gspca_dev, 0x50, state, 0, NULL, 0);
130 if (ret < 0)
131 return ret;
132
133 if (state)
134 ret = vicam_control_msg(gspca_dev, 0x55, 1, 0, NULL, 0);
135
136 return ret;
137}
138
139
140
141
142static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size)
143{
144 struct sd *sd = (struct sd *)gspca_dev;
145 int ret, unscaled_height, act_len = 0;
146 u8 *req_data = gspca_dev->usb_buf;
147
148 memset(req_data, 0, 16);
149 req_data[0] = sd->ctrls[GAIN].val;
150 if (gspca_dev->width == 256)
151 req_data[1] |= 0x01;
152 if (gspca_dev->height <= 122) {
153 req_data[1] |= 0x10;
154 unscaled_height = gspca_dev->height * 2;
155 } else
156 unscaled_height = gspca_dev->height;
157 req_data[2] = 0x90;
158 if (unscaled_height <= 200)
159 req_data[3] = 0x06;
160 else if (unscaled_height <= 242)
161 req_data[3] = 0x07;
162 else
163 req_data[3] = 0x08;
164
165 if (sd->ctrls[EXPOSURE].val < 256) {
166
167 req_data[4] = 255 - sd->ctrls[EXPOSURE].val;
168 req_data[5] = 0x00;
169 req_data[6] = 0x00;
170 req_data[7] = 0x01;
171 } else {
172
173 req_data[4] = 0x00;
174 req_data[5] = 0x00;
175 req_data[6] = sd->ctrls[EXPOSURE].val & 0xFF;
176 req_data[7] = sd->ctrls[EXPOSURE].val >> 8;
177 }
178 req_data[8] = ((244 - unscaled_height) / 2) & ~0x01;
179
180
181 mutex_lock(&gspca_dev->usb_lock);
182 ret = vicam_control_msg(gspca_dev, 0x51, 0x80, 0, req_data, 16);
183 mutex_unlock(&gspca_dev->usb_lock);
184 if (ret < 0)
185 return ret;
186
187 ret = usb_bulk_msg(gspca_dev->dev,
188 usb_rcvbulkpipe(gspca_dev->dev, 0x81),
189 data, size, &act_len, 10000);
190
191 if (ret < 0 || act_len != size) {
192 err("bulk read fail (%d) len %d/%d",
193 ret, act_len, size);
194 return -EIO;
195 }
196 return 0;
197}
198
199
200
201
202
203
204
205
206
207
208static void vicam_dostream(struct work_struct *work)
209{
210 struct sd *sd = container_of(work, struct sd, work_struct);
211 struct gspca_dev *gspca_dev = &sd->gspca_dev;
212 int ret, frame_sz;
213 u8 *buffer;
214
215 frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage +
216 HEADER_SIZE;
217 buffer = kmalloc(frame_sz, GFP_KERNEL | GFP_DMA);
218 if (!buffer) {
219 err("Couldn't allocate USB buffer");
220 goto exit;
221 }
222
223 while (gspca_dev->present && gspca_dev->streaming) {
224 ret = vicam_read_frame(gspca_dev, buffer, frame_sz);
225 if (ret < 0)
226 break;
227
228
229
230
231
232
233 gspca_frame_add(gspca_dev, FIRST_PACKET,
234 buffer + HEADER_SIZE,
235 frame_sz - HEADER_SIZE);
236 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
237 }
238exit:
239 kfree(buffer);
240}
241
242
243static int sd_config(struct gspca_dev *gspca_dev,
244 const struct usb_device_id *id)
245{
246 struct cam *cam = &gspca_dev->cam;
247 struct sd *sd = (struct sd *)gspca_dev;
248
249
250 cam->bulk = 1;
251 cam->bulk_size = 64;
252 cam->cam_mode = vicam_mode;
253 cam->nmodes = ARRAY_SIZE(vicam_mode);
254 cam->ctrls = sd->ctrls;
255
256 INIT_WORK(&sd->work_struct, vicam_dostream);
257
258 return 0;
259}
260
261
262static int sd_init(struct gspca_dev *gspca_dev)
263{
264 int ret;
265 const struct ihex_binrec *rec;
266 const struct firmware *uninitialized_var(fw);
267 u8 *firmware_buf;
268
269 ret = request_ihex_firmware(&fw, "vicam/firmware.fw",
270 &gspca_dev->dev->dev);
271 if (ret) {
272 err("Failed to load \"vicam/firmware.fw\": %d\n", ret);
273 return ret;
274 }
275
276 firmware_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
277 if (!firmware_buf) {
278 ret = -ENOMEM;
279 goto exit;
280 }
281 for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) {
282 memcpy(firmware_buf, rec->data, be16_to_cpu(rec->len));
283 ret = vicam_control_msg(gspca_dev, 0xff, 0, 0, firmware_buf,
284 be16_to_cpu(rec->len));
285 if (ret < 0)
286 break;
287 }
288
289 kfree(firmware_buf);
290exit:
291 release_firmware(fw);
292 return ret;
293}
294
295
296static int sd_start(struct gspca_dev *gspca_dev)
297{
298 struct sd *sd = (struct sd *)gspca_dev;
299 int ret;
300
301 ret = vicam_set_camera_power(gspca_dev, 1);
302 if (ret < 0)
303 return ret;
304
305
306 sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
307 queue_work(sd->work_thread, &sd->work_struct);
308
309 return 0;
310}
311
312
313
314static void sd_stop0(struct gspca_dev *gspca_dev)
315{
316 struct sd *dev = (struct sd *)gspca_dev;
317
318
319 mutex_unlock(&gspca_dev->usb_lock);
320
321 destroy_workqueue(dev->work_thread);
322 dev->work_thread = NULL;
323 mutex_lock(&gspca_dev->usb_lock);
324
325 vicam_set_camera_power(gspca_dev, 0);
326}
327
328
329static const struct usb_device_id device_table[] = {
330 {USB_DEVICE(0x04c1, 0x009d)},
331 {USB_DEVICE(0x0602, 0x1001)},
332 {}
333};
334
335MODULE_DEVICE_TABLE(usb, device_table);
336
337
338static const struct sd_desc sd_desc = {
339 .name = MODULE_NAME,
340 .ctrls = sd_ctrls,
341 .nctrls = ARRAY_SIZE(sd_ctrls),
342 .config = sd_config,
343 .init = sd_init,
344 .start = sd_start,
345 .stop0 = sd_stop0,
346};
347
348
349static int sd_probe(struct usb_interface *intf,
350 const struct usb_device_id *id)
351{
352 return gspca_dev_probe(intf, id,
353 &sd_desc,
354 sizeof(struct sd),
355 THIS_MODULE);
356}
357
358static struct usb_driver sd_driver = {
359 .name = MODULE_NAME,
360 .id_table = device_table,
361 .probe = sd_probe,
362 .disconnect = gspca_disconnect,
363#ifdef CONFIG_PM
364 .suspend = gspca_suspend,
365 .resume = gspca_resume,
366#endif
367};
368
369
370static int __init sd_mod_init(void)
371{
372 return usb_register(&sd_driver);
373}
374
375static void __exit sd_mod_exit(void)
376{
377 usb_deregister(&sd_driver);
378}
379
380module_init(sd_mod_init);
381module_exit(sd_mod_exit);
382