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
30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
32#define MODULE_NAME "sq905c"
33
34#include <linux/workqueue.h>
35#include <linux/slab.h>
36#include "gspca.h"
37
38MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
39MODULE_DESCRIPTION("GSPCA/SQ905C USB Camera Driver");
40MODULE_LICENSE("GPL");
41
42
43#define SQ905C_CMD_TIMEOUT 500
44#define SQ905C_DATA_TIMEOUT 1000
45
46
47#define SQ905C_MAX_TRANSFER 0x8000
48
49#define FRAME_HEADER_LEN 0x50
50
51
52#define SQ905C_CLEAR 0xa0
53#define SQ905C_GET_ID 0x14f4
54#define SQ905C_CAPTURE_LOW 0xa040
55#define SQ905C_CAPTURE_MED 0x1440
56#define SQ905C_CAPTURE_HI 0x2840
57
58
59#define SQ905C_CAPTURE_INDEX 0x110f
60
61
62struct sd {
63 struct gspca_dev gspca_dev;
64 const struct v4l2_pix_format *cap_mode;
65
66 struct work_struct work_struct;
67 struct workqueue_struct *work_thread;
68};
69
70
71
72
73
74
75static struct v4l2_pix_format sq905c_mode[] = {
76 { 320, 240, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
77 .bytesperline = 320,
78 .sizeimage = 320 * 240,
79 .colorspace = V4L2_COLORSPACE_SRGB,
80 .priv = 0},
81 { 640, 480, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
82 .bytesperline = 640,
83 .sizeimage = 640 * 480,
84 .colorspace = V4L2_COLORSPACE_SRGB,
85 .priv = 0}
86};
87
88
89static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index)
90{
91 int ret;
92
93 ret = usb_control_msg(gspca_dev->dev,
94 usb_sndctrlpipe(gspca_dev->dev, 0),
95 USB_REQ_SYNCH_FRAME,
96 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
97 command, index, NULL, 0,
98 SQ905C_CMD_TIMEOUT);
99 if (ret < 0) {
100 pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
101 return ret;
102 }
103
104 return 0;
105}
106
107static int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index,
108 int size)
109{
110 int ret;
111
112 ret = usb_control_msg(gspca_dev->dev,
113 usb_rcvctrlpipe(gspca_dev->dev, 0),
114 USB_REQ_SYNCH_FRAME,
115 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
116 command, index, gspca_dev->usb_buf, size,
117 SQ905C_CMD_TIMEOUT);
118 if (ret < 0) {
119 pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
120 return ret;
121 }
122
123 return 0;
124}
125
126
127
128
129
130
131
132
133
134static void sq905c_dostream(struct work_struct *work)
135{
136 struct sd *dev = container_of(work, struct sd, work_struct);
137 struct gspca_dev *gspca_dev = &dev->gspca_dev;
138 int bytes_left;
139 int data_len;
140 int act_len;
141 int packet_type;
142 int ret;
143 u8 *buffer;
144
145 buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
146 if (!buffer) {
147 pr_err("Couldn't allocate USB buffer\n");
148 goto quit_stream;
149 }
150
151 while (gspca_dev->present && gspca_dev->streaming) {
152#ifdef CONFIG_PM
153 if (gspca_dev->frozen)
154 break;
155#endif
156
157 ret = usb_bulk_msg(gspca_dev->dev,
158 usb_rcvbulkpipe(gspca_dev->dev, 0x81),
159 buffer, FRAME_HEADER_LEN, &act_len,
160 SQ905C_DATA_TIMEOUT);
161 PDEBUG(D_STREAM,
162 "Got %d bytes out of %d for header",
163 act_len, FRAME_HEADER_LEN);
164 if (ret < 0 || act_len < FRAME_HEADER_LEN)
165 goto quit_stream;
166
167 bytes_left = buffer[0x40]|(buffer[0x41]<<8)|(buffer[0x42]<<16)
168 |(buffer[0x43]<<24);
169 PDEBUG(D_STREAM, "bytes_left = 0x%x", bytes_left);
170
171 packet_type = FIRST_PACKET;
172 gspca_frame_add(gspca_dev, packet_type,
173 buffer, FRAME_HEADER_LEN);
174 while (bytes_left > 0 && gspca_dev->present) {
175 data_len = bytes_left > SQ905C_MAX_TRANSFER ?
176 SQ905C_MAX_TRANSFER : bytes_left;
177 ret = usb_bulk_msg(gspca_dev->dev,
178 usb_rcvbulkpipe(gspca_dev->dev, 0x81),
179 buffer, data_len, &act_len,
180 SQ905C_DATA_TIMEOUT);
181 if (ret < 0 || act_len < data_len)
182 goto quit_stream;
183 PDEBUG(D_STREAM,
184 "Got %d bytes out of %d for frame",
185 data_len, bytes_left);
186 bytes_left -= data_len;
187 if (bytes_left == 0)
188 packet_type = LAST_PACKET;
189 else
190 packet_type = INTER_PACKET;
191 gspca_frame_add(gspca_dev, packet_type,
192 buffer, data_len);
193 }
194 }
195quit_stream:
196 if (gspca_dev->present) {
197 mutex_lock(&gspca_dev->usb_lock);
198 sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
199 mutex_unlock(&gspca_dev->usb_lock);
200 }
201 kfree(buffer);
202}
203
204
205static int sd_config(struct gspca_dev *gspca_dev,
206 const struct usb_device_id *id)
207{
208 struct cam *cam = &gspca_dev->cam;
209 struct sd *dev = (struct sd *) gspca_dev;
210 int ret;
211
212 PDEBUG(D_PROBE,
213 "SQ9050 camera detected"
214 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
215
216 ret = sq905c_command(gspca_dev, SQ905C_GET_ID, 0);
217 if (ret < 0) {
218 PERR("Get version command failed");
219 return ret;
220 }
221
222 ret = sq905c_read(gspca_dev, 0xf5, 0, 20);
223 if (ret < 0) {
224 PERR("Reading version command failed");
225 return ret;
226 }
227
228 PDEBUG(D_PROBE,
229 "SQ9050 ID string: %02x - %*ph",
230 gspca_dev->usb_buf[3], 6, gspca_dev->usb_buf + 14);
231
232 cam->cam_mode = sq905c_mode;
233 cam->nmodes = 2;
234 if (gspca_dev->usb_buf[15] == 0)
235 cam->nmodes = 1;
236
237 cam->bulk_size = 32;
238 cam->bulk = 1;
239 INIT_WORK(&dev->work_struct, sq905c_dostream);
240 return 0;
241}
242
243
244
245static void sd_stop0(struct gspca_dev *gspca_dev)
246{
247 struct sd *dev = (struct sd *) gspca_dev;
248
249
250 mutex_unlock(&gspca_dev->usb_lock);
251
252 destroy_workqueue(dev->work_thread);
253 dev->work_thread = NULL;
254 mutex_lock(&gspca_dev->usb_lock);
255}
256
257
258static int sd_init(struct gspca_dev *gspca_dev)
259{
260 int ret;
261
262
263 ret = sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
264 return ret;
265}
266
267
268static int sd_start(struct gspca_dev *gspca_dev)
269{
270 struct sd *dev = (struct sd *) gspca_dev;
271 int ret;
272
273 dev->cap_mode = gspca_dev->cam.cam_mode;
274
275 switch (gspca_dev->width) {
276 case 640:
277 PDEBUG(D_STREAM, "Start streaming at high resolution");
278 dev->cap_mode++;
279 ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_HI,
280 SQ905C_CAPTURE_INDEX);
281 break;
282 default:
283 PDEBUG(D_STREAM, "Start streaming at medium resolution");
284 ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_MED,
285 SQ905C_CAPTURE_INDEX);
286 }
287
288 if (ret < 0) {
289 PERR("Start streaming command failed");
290 return ret;
291 }
292
293 dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
294 queue_work(dev->work_thread, &dev->work_struct);
295
296 return 0;
297}
298
299
300static const struct usb_device_id device_table[] = {
301 {USB_DEVICE(0x2770, 0x905c)},
302 {USB_DEVICE(0x2770, 0x9050)},
303 {USB_DEVICE(0x2770, 0x9051)},
304 {USB_DEVICE(0x2770, 0x9052)},
305 {USB_DEVICE(0x2770, 0x913d)},
306 {}
307};
308
309MODULE_DEVICE_TABLE(usb, device_table);
310
311
312static const struct sd_desc sd_desc = {
313 .name = MODULE_NAME,
314 .config = sd_config,
315 .init = sd_init,
316 .start = sd_start,
317 .stop0 = sd_stop0,
318};
319
320
321static int sd_probe(struct usb_interface *intf,
322 const struct usb_device_id *id)
323{
324 return gspca_dev_probe(intf, id,
325 &sd_desc,
326 sizeof(struct sd),
327 THIS_MODULE);
328}
329
330static struct usb_driver sd_driver = {
331 .name = MODULE_NAME,
332 .id_table = device_table,
333 .probe = sd_probe,
334 .disconnect = gspca_disconnect,
335#ifdef CONFIG_PM
336 .suspend = gspca_suspend,
337 .resume = gspca_resume,
338 .reset_resume = gspca_resume,
339#endif
340};
341
342module_usb_driver(sd_driver);
343