1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Benq DC E300 subdriver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2009 Jean-Francois Moine (http://moinejf.free.fr)
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #define MODULE_NAME "benq"
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include "gspca.h"
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
15*4882a593Smuzhiyun MODULE_DESCRIPTION("Benq DC E300 USB Camera Driver");
16*4882a593Smuzhiyun MODULE_LICENSE("GPL");
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun /* specific webcam descriptor */
19*4882a593Smuzhiyun struct sd {
20*4882a593Smuzhiyun struct gspca_dev gspca_dev; /* !! must be the first item */
21*4882a593Smuzhiyun };
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun static const struct v4l2_pix_format vga_mode[] = {
24*4882a593Smuzhiyun {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
25*4882a593Smuzhiyun .bytesperline = 320,
26*4882a593Smuzhiyun .sizeimage = 320 * 240 * 3 / 8 + 590,
27*4882a593Smuzhiyun .colorspace = V4L2_COLORSPACE_JPEG},
28*4882a593Smuzhiyun };
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static void sd_isoc_irq(struct urb *urb);
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /* -- write a register -- */
reg_w(struct gspca_dev * gspca_dev,u16 value,u16 index)33*4882a593Smuzhiyun static void reg_w(struct gspca_dev *gspca_dev,
34*4882a593Smuzhiyun u16 value, u16 index)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun struct usb_device *dev = gspca_dev->dev;
37*4882a593Smuzhiyun int ret;
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun if (gspca_dev->usb_err < 0)
40*4882a593Smuzhiyun return;
41*4882a593Smuzhiyun ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
42*4882a593Smuzhiyun 0x02,
43*4882a593Smuzhiyun USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
44*4882a593Smuzhiyun value,
45*4882a593Smuzhiyun index,
46*4882a593Smuzhiyun NULL,
47*4882a593Smuzhiyun 0,
48*4882a593Smuzhiyun 500);
49*4882a593Smuzhiyun if (ret < 0) {
50*4882a593Smuzhiyun pr_err("reg_w err %d\n", ret);
51*4882a593Smuzhiyun gspca_dev->usb_err = ret;
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /* this function is called at probe time */
sd_config(struct gspca_dev * gspca_dev,const struct usb_device_id * id)56*4882a593Smuzhiyun static int sd_config(struct gspca_dev *gspca_dev,
57*4882a593Smuzhiyun const struct usb_device_id *id)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun gspca_dev->cam.cam_mode = vga_mode;
60*4882a593Smuzhiyun gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
61*4882a593Smuzhiyun gspca_dev->cam.no_urb_create = 1;
62*4882a593Smuzhiyun return 0;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun /* this function is called at probe and resume time */
sd_init(struct gspca_dev * gspca_dev)66*4882a593Smuzhiyun static int sd_init(struct gspca_dev *gspca_dev)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun return 0;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun /* -- start the camera -- */
sd_start(struct gspca_dev * gspca_dev)72*4882a593Smuzhiyun static int sd_start(struct gspca_dev *gspca_dev)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun struct urb *urb;
75*4882a593Smuzhiyun int i, n;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */
78*4882a593Smuzhiyun #if MAX_NURBS < 4
79*4882a593Smuzhiyun #error "Not enough URBs in the gspca table"
80*4882a593Smuzhiyun #endif
81*4882a593Smuzhiyun #define SD_PKT_SZ 64
82*4882a593Smuzhiyun #define SD_NPKT 32
83*4882a593Smuzhiyun for (n = 0; n < 4; n++) {
84*4882a593Smuzhiyun urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
85*4882a593Smuzhiyun if (!urb)
86*4882a593Smuzhiyun return -ENOMEM;
87*4882a593Smuzhiyun gspca_dev->urb[n] = urb;
88*4882a593Smuzhiyun urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
89*4882a593Smuzhiyun SD_PKT_SZ * SD_NPKT,
90*4882a593Smuzhiyun GFP_KERNEL,
91*4882a593Smuzhiyun &urb->transfer_dma);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun if (urb->transfer_buffer == NULL) {
94*4882a593Smuzhiyun pr_err("usb_alloc_coherent failed\n");
95*4882a593Smuzhiyun return -ENOMEM;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun urb->dev = gspca_dev->dev;
98*4882a593Smuzhiyun urb->context = gspca_dev;
99*4882a593Smuzhiyun urb->transfer_buffer_length = SD_PKT_SZ * SD_NPKT;
100*4882a593Smuzhiyun urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
101*4882a593Smuzhiyun n & 1 ? 0x82 : 0x83);
102*4882a593Smuzhiyun urb->transfer_flags = URB_ISO_ASAP
103*4882a593Smuzhiyun | URB_NO_TRANSFER_DMA_MAP;
104*4882a593Smuzhiyun urb->interval = 1;
105*4882a593Smuzhiyun urb->complete = sd_isoc_irq;
106*4882a593Smuzhiyun urb->number_of_packets = SD_NPKT;
107*4882a593Smuzhiyun for (i = 0; i < SD_NPKT; i++) {
108*4882a593Smuzhiyun urb->iso_frame_desc[i].length = SD_PKT_SZ;
109*4882a593Smuzhiyun urb->iso_frame_desc[i].offset = SD_PKT_SZ * i;
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun return gspca_dev->usb_err;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
sd_stopN(struct gspca_dev * gspca_dev)116*4882a593Smuzhiyun static void sd_stopN(struct gspca_dev *gspca_dev)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun struct usb_interface *intf;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun reg_w(gspca_dev, 0x003c, 0x0003);
121*4882a593Smuzhiyun reg_w(gspca_dev, 0x003c, 0x0004);
122*4882a593Smuzhiyun reg_w(gspca_dev, 0x003c, 0x0005);
123*4882a593Smuzhiyun reg_w(gspca_dev, 0x003c, 0x0006);
124*4882a593Smuzhiyun reg_w(gspca_dev, 0x003c, 0x0007);
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
127*4882a593Smuzhiyun usb_set_interface(gspca_dev->dev, gspca_dev->iface,
128*4882a593Smuzhiyun intf->num_altsetting - 1);
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
sd_pkt_scan(struct gspca_dev * gspca_dev,u8 * data,int len)131*4882a593Smuzhiyun static void sd_pkt_scan(struct gspca_dev *gspca_dev,
132*4882a593Smuzhiyun u8 *data, /* isoc packet */
133*4882a593Smuzhiyun int len) /* iso packet length */
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun /* unused */
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun /* reception of an URB */
sd_isoc_irq(struct urb * urb)139*4882a593Smuzhiyun static void sd_isoc_irq(struct urb *urb)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
142*4882a593Smuzhiyun struct urb *urb0;
143*4882a593Smuzhiyun u8 *data;
144*4882a593Smuzhiyun int i, st;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun gspca_dbg(gspca_dev, D_PACK, "sd isoc irq\n");
147*4882a593Smuzhiyun if (!gspca_dev->streaming)
148*4882a593Smuzhiyun return;
149*4882a593Smuzhiyun if (urb->status != 0) {
150*4882a593Smuzhiyun if (urb->status == -ESHUTDOWN)
151*4882a593Smuzhiyun return; /* disconnection */
152*4882a593Smuzhiyun #ifdef CONFIG_PM
153*4882a593Smuzhiyun if (gspca_dev->frozen)
154*4882a593Smuzhiyun return;
155*4882a593Smuzhiyun #endif
156*4882a593Smuzhiyun pr_err("urb status: %d\n", urb->status);
157*4882a593Smuzhiyun return;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun /* if this is a control URN (ep 0x83), wait */
161*4882a593Smuzhiyun if (urb == gspca_dev->urb[0] || urb == gspca_dev->urb[2])
162*4882a593Smuzhiyun return;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /* scan both received URBs */
165*4882a593Smuzhiyun if (urb == gspca_dev->urb[1])
166*4882a593Smuzhiyun urb0 = gspca_dev->urb[0];
167*4882a593Smuzhiyun else
168*4882a593Smuzhiyun urb0 = gspca_dev->urb[2];
169*4882a593Smuzhiyun for (i = 0; i < urb->number_of_packets; i++) {
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun /* check the packet status and length */
172*4882a593Smuzhiyun if (urb0->iso_frame_desc[i].actual_length != SD_PKT_SZ
173*4882a593Smuzhiyun || urb->iso_frame_desc[i].actual_length != SD_PKT_SZ) {
174*4882a593Smuzhiyun gspca_err(gspca_dev, "ISOC bad lengths %d / %d\n",
175*4882a593Smuzhiyun urb0->iso_frame_desc[i].actual_length,
176*4882a593Smuzhiyun urb->iso_frame_desc[i].actual_length);
177*4882a593Smuzhiyun gspca_dev->last_packet_type = DISCARD_PACKET;
178*4882a593Smuzhiyun continue;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun st = urb0->iso_frame_desc[i].status;
181*4882a593Smuzhiyun if (st == 0)
182*4882a593Smuzhiyun st = urb->iso_frame_desc[i].status;
183*4882a593Smuzhiyun if (st) {
184*4882a593Smuzhiyun pr_err("ISOC data error: [%d] status=%d\n",
185*4882a593Smuzhiyun i, st);
186*4882a593Smuzhiyun gspca_dev->last_packet_type = DISCARD_PACKET;
187*4882a593Smuzhiyun continue;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun /*
191*4882a593Smuzhiyun * The images are received in URBs of different endpoints
192*4882a593Smuzhiyun * (0x83 and 0x82).
193*4882a593Smuzhiyun * Image pieces in URBs of ep 0x83 are continuated in URBs of
194*4882a593Smuzhiyun * ep 0x82 of the same index.
195*4882a593Smuzhiyun * The packets in the URBs of endpoint 0x83 start with:
196*4882a593Smuzhiyun * - 80 ba/bb 00 00 = start of image followed by 'ff d8'
197*4882a593Smuzhiyun * - 04 ba/bb oo oo = image piece
198*4882a593Smuzhiyun * where 'oo oo' is the image offset
199*4882a593Smuzhiyun (not checked)
200*4882a593Smuzhiyun * - (other -> bad frame)
201*4882a593Smuzhiyun * The images are JPEG encoded with full header and
202*4882a593Smuzhiyun * normal ff escape.
203*4882a593Smuzhiyun * The end of image ('ff d9') may occur in any URB.
204*4882a593Smuzhiyun * (not checked)
205*4882a593Smuzhiyun */
206*4882a593Smuzhiyun data = (u8 *) urb0->transfer_buffer
207*4882a593Smuzhiyun + urb0->iso_frame_desc[i].offset;
208*4882a593Smuzhiyun if (data[0] == 0x80 && (data[1] & 0xfe) == 0xba) {
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /* new image */
211*4882a593Smuzhiyun gspca_frame_add(gspca_dev, LAST_PACKET,
212*4882a593Smuzhiyun NULL, 0);
213*4882a593Smuzhiyun gspca_frame_add(gspca_dev, FIRST_PACKET,
214*4882a593Smuzhiyun data + 4, SD_PKT_SZ - 4);
215*4882a593Smuzhiyun } else if (data[0] == 0x04 && (data[1] & 0xfe) == 0xba) {
216*4882a593Smuzhiyun gspca_frame_add(gspca_dev, INTER_PACKET,
217*4882a593Smuzhiyun data + 4, SD_PKT_SZ - 4);
218*4882a593Smuzhiyun } else {
219*4882a593Smuzhiyun gspca_dev->last_packet_type = DISCARD_PACKET;
220*4882a593Smuzhiyun continue;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun data = (u8 *) urb->transfer_buffer
223*4882a593Smuzhiyun + urb->iso_frame_desc[i].offset;
224*4882a593Smuzhiyun gspca_frame_add(gspca_dev, INTER_PACKET,
225*4882a593Smuzhiyun data, SD_PKT_SZ);
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun /* resubmit the URBs */
229*4882a593Smuzhiyun st = usb_submit_urb(urb0, GFP_ATOMIC);
230*4882a593Smuzhiyun if (st < 0)
231*4882a593Smuzhiyun pr_err("usb_submit_urb(0) ret %d\n", st);
232*4882a593Smuzhiyun st = usb_submit_urb(urb, GFP_ATOMIC);
233*4882a593Smuzhiyun if (st < 0)
234*4882a593Smuzhiyun pr_err("usb_submit_urb() ret %d\n", st);
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun /* sub-driver description */
238*4882a593Smuzhiyun static const struct sd_desc sd_desc = {
239*4882a593Smuzhiyun .name = MODULE_NAME,
240*4882a593Smuzhiyun .config = sd_config,
241*4882a593Smuzhiyun .init = sd_init,
242*4882a593Smuzhiyun .start = sd_start,
243*4882a593Smuzhiyun .stopN = sd_stopN,
244*4882a593Smuzhiyun .pkt_scan = sd_pkt_scan,
245*4882a593Smuzhiyun };
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun /* -- module initialisation -- */
248*4882a593Smuzhiyun static const struct usb_device_id device_table[] = {
249*4882a593Smuzhiyun {USB_DEVICE(0x04a5, 0x3035)},
250*4882a593Smuzhiyun {}
251*4882a593Smuzhiyun };
252*4882a593Smuzhiyun MODULE_DEVICE_TABLE(usb, device_table);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun /* -- device connect -- */
sd_probe(struct usb_interface * intf,const struct usb_device_id * id)255*4882a593Smuzhiyun static int sd_probe(struct usb_interface *intf,
256*4882a593Smuzhiyun const struct usb_device_id *id)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
259*4882a593Smuzhiyun THIS_MODULE);
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun static struct usb_driver sd_driver = {
263*4882a593Smuzhiyun .name = MODULE_NAME,
264*4882a593Smuzhiyun .id_table = device_table,
265*4882a593Smuzhiyun .probe = sd_probe,
266*4882a593Smuzhiyun .disconnect = gspca_disconnect,
267*4882a593Smuzhiyun #ifdef CONFIG_PM
268*4882a593Smuzhiyun .suspend = gspca_suspend,
269*4882a593Smuzhiyun .resume = gspca_resume,
270*4882a593Smuzhiyun .reset_resume = gspca_resume,
271*4882a593Smuzhiyun #endif
272*4882a593Smuzhiyun };
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun module_usb_driver(sd_driver);
275