10c0d06caSMauro Carvalho Chehab /* 20c0d06caSMauro Carvalho Chehab * Benq DC E300 subdriver 30c0d06caSMauro Carvalho Chehab * 40c0d06caSMauro Carvalho Chehab * Copyright (C) 2009 Jean-Francois Moine (http://moinejf.free.fr) 50c0d06caSMauro Carvalho Chehab * 60c0d06caSMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 70c0d06caSMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 80c0d06caSMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 90c0d06caSMauro Carvalho Chehab * any later version. 100c0d06caSMauro Carvalho Chehab * 110c0d06caSMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 120c0d06caSMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 130c0d06caSMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 140c0d06caSMauro Carvalho Chehab * GNU General Public License for more details. 150c0d06caSMauro Carvalho Chehab */ 160c0d06caSMauro Carvalho Chehab 170c0d06caSMauro Carvalho Chehab #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 180c0d06caSMauro Carvalho Chehab 190c0d06caSMauro Carvalho Chehab #define MODULE_NAME "benq" 200c0d06caSMauro Carvalho Chehab 210c0d06caSMauro Carvalho Chehab #include "gspca.h" 220c0d06caSMauro Carvalho Chehab 230c0d06caSMauro Carvalho Chehab MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); 240c0d06caSMauro Carvalho Chehab MODULE_DESCRIPTION("Benq DC E300 USB Camera Driver"); 250c0d06caSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 260c0d06caSMauro Carvalho Chehab 270c0d06caSMauro Carvalho Chehab /* specific webcam descriptor */ 280c0d06caSMauro Carvalho Chehab struct sd { 290c0d06caSMauro Carvalho Chehab struct gspca_dev gspca_dev; /* !! must be the first item */ 300c0d06caSMauro Carvalho Chehab }; 310c0d06caSMauro Carvalho Chehab 320c0d06caSMauro Carvalho Chehab static const struct v4l2_pix_format vga_mode[] = { 330c0d06caSMauro Carvalho Chehab {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 340c0d06caSMauro Carvalho Chehab .bytesperline = 320, 350c0d06caSMauro Carvalho Chehab .sizeimage = 320 * 240 * 3 / 8 + 590, 360c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_JPEG}, 370c0d06caSMauro Carvalho Chehab }; 380c0d06caSMauro Carvalho Chehab 390c0d06caSMauro Carvalho Chehab static void sd_isoc_irq(struct urb *urb); 400c0d06caSMauro Carvalho Chehab 410c0d06caSMauro Carvalho Chehab /* -- write a register -- */ 420c0d06caSMauro Carvalho Chehab static void reg_w(struct gspca_dev *gspca_dev, 430c0d06caSMauro Carvalho Chehab u16 value, u16 index) 440c0d06caSMauro Carvalho Chehab { 450c0d06caSMauro Carvalho Chehab struct usb_device *dev = gspca_dev->dev; 460c0d06caSMauro Carvalho Chehab int ret; 470c0d06caSMauro Carvalho Chehab 480c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 490c0d06caSMauro Carvalho Chehab return; 500c0d06caSMauro Carvalho Chehab ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 510c0d06caSMauro Carvalho Chehab 0x02, 520c0d06caSMauro Carvalho Chehab USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 530c0d06caSMauro Carvalho Chehab value, 540c0d06caSMauro Carvalho Chehab index, 550c0d06caSMauro Carvalho Chehab NULL, 560c0d06caSMauro Carvalho Chehab 0, 570c0d06caSMauro Carvalho Chehab 500); 580c0d06caSMauro Carvalho Chehab if (ret < 0) { 590c0d06caSMauro Carvalho Chehab pr_err("reg_w err %d\n", ret); 600c0d06caSMauro Carvalho Chehab gspca_dev->usb_err = ret; 610c0d06caSMauro Carvalho Chehab } 620c0d06caSMauro Carvalho Chehab } 630c0d06caSMauro Carvalho Chehab 640c0d06caSMauro Carvalho Chehab /* this function is called at probe time */ 650c0d06caSMauro Carvalho Chehab static int sd_config(struct gspca_dev *gspca_dev, 660c0d06caSMauro Carvalho Chehab const struct usb_device_id *id) 670c0d06caSMauro Carvalho Chehab { 680c0d06caSMauro Carvalho Chehab gspca_dev->cam.cam_mode = vga_mode; 690c0d06caSMauro Carvalho Chehab gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); 700c0d06caSMauro Carvalho Chehab gspca_dev->cam.no_urb_create = 1; 710c0d06caSMauro Carvalho Chehab return 0; 720c0d06caSMauro Carvalho Chehab } 730c0d06caSMauro Carvalho Chehab 740c0d06caSMauro Carvalho Chehab /* this function is called at probe and resume time */ 750c0d06caSMauro Carvalho Chehab static int sd_init(struct gspca_dev *gspca_dev) 760c0d06caSMauro Carvalho Chehab { 770c0d06caSMauro Carvalho Chehab return 0; 780c0d06caSMauro Carvalho Chehab } 790c0d06caSMauro Carvalho Chehab 800c0d06caSMauro Carvalho Chehab /* -- start the camera -- */ 810c0d06caSMauro Carvalho Chehab static int sd_start(struct gspca_dev *gspca_dev) 820c0d06caSMauro Carvalho Chehab { 830c0d06caSMauro Carvalho Chehab struct urb *urb; 840c0d06caSMauro Carvalho Chehab int i, n; 850c0d06caSMauro Carvalho Chehab 860c0d06caSMauro Carvalho Chehab /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */ 870c0d06caSMauro Carvalho Chehab #if MAX_NURBS < 4 880c0d06caSMauro Carvalho Chehab #error "Not enough URBs in the gspca table" 890c0d06caSMauro Carvalho Chehab #endif 900c0d06caSMauro Carvalho Chehab #define SD_PKT_SZ 64 910c0d06caSMauro Carvalho Chehab #define SD_NPKT 32 920c0d06caSMauro Carvalho Chehab for (n = 0; n < 4; n++) { 930c0d06caSMauro Carvalho Chehab urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL); 9460e36999SWolfram Sang if (!urb) 950c0d06caSMauro Carvalho Chehab return -ENOMEM; 960c0d06caSMauro Carvalho Chehab gspca_dev->urb[n] = urb; 970c0d06caSMauro Carvalho Chehab urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev, 980c0d06caSMauro Carvalho Chehab SD_PKT_SZ * SD_NPKT, 990c0d06caSMauro Carvalho Chehab GFP_KERNEL, 1000c0d06caSMauro Carvalho Chehab &urb->transfer_dma); 1010c0d06caSMauro Carvalho Chehab 1020c0d06caSMauro Carvalho Chehab if (urb->transfer_buffer == NULL) { 1030c0d06caSMauro Carvalho Chehab pr_err("usb_alloc_coherent failed\n"); 1040c0d06caSMauro Carvalho Chehab return -ENOMEM; 1050c0d06caSMauro Carvalho Chehab } 1060c0d06caSMauro Carvalho Chehab urb->dev = gspca_dev->dev; 1070c0d06caSMauro Carvalho Chehab urb->context = gspca_dev; 1080c0d06caSMauro Carvalho Chehab urb->transfer_buffer_length = SD_PKT_SZ * SD_NPKT; 1090c0d06caSMauro Carvalho Chehab urb->pipe = usb_rcvisocpipe(gspca_dev->dev, 1100c0d06caSMauro Carvalho Chehab n & 1 ? 0x82 : 0x83); 1110c0d06caSMauro Carvalho Chehab urb->transfer_flags = URB_ISO_ASAP 1120c0d06caSMauro Carvalho Chehab | URB_NO_TRANSFER_DMA_MAP; 1130c0d06caSMauro Carvalho Chehab urb->interval = 1; 1140c0d06caSMauro Carvalho Chehab urb->complete = sd_isoc_irq; 1150c0d06caSMauro Carvalho Chehab urb->number_of_packets = SD_NPKT; 1160c0d06caSMauro Carvalho Chehab for (i = 0; i < SD_NPKT; i++) { 1170c0d06caSMauro Carvalho Chehab urb->iso_frame_desc[i].length = SD_PKT_SZ; 1180c0d06caSMauro Carvalho Chehab urb->iso_frame_desc[i].offset = SD_PKT_SZ * i; 1190c0d06caSMauro Carvalho Chehab } 1200c0d06caSMauro Carvalho Chehab } 1210c0d06caSMauro Carvalho Chehab 1220c0d06caSMauro Carvalho Chehab return gspca_dev->usb_err; 1230c0d06caSMauro Carvalho Chehab } 1240c0d06caSMauro Carvalho Chehab 1250c0d06caSMauro Carvalho Chehab static void sd_stopN(struct gspca_dev *gspca_dev) 1260c0d06caSMauro Carvalho Chehab { 1270c0d06caSMauro Carvalho Chehab struct usb_interface *intf; 1280c0d06caSMauro Carvalho Chehab 1290c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x003c, 0x0003); 1300c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x003c, 0x0004); 1310c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x003c, 0x0005); 1320c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x003c, 0x0006); 1330c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x003c, 0x0007); 1340c0d06caSMauro Carvalho Chehab 1350c0d06caSMauro Carvalho Chehab intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); 1360c0d06caSMauro Carvalho Chehab usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1370c0d06caSMauro Carvalho Chehab intf->num_altsetting - 1); 1380c0d06caSMauro Carvalho Chehab } 1390c0d06caSMauro Carvalho Chehab 1400c0d06caSMauro Carvalho Chehab static void sd_pkt_scan(struct gspca_dev *gspca_dev, 1410c0d06caSMauro Carvalho Chehab u8 *data, /* isoc packet */ 1420c0d06caSMauro Carvalho Chehab int len) /* iso packet length */ 1430c0d06caSMauro Carvalho Chehab { 1440c0d06caSMauro Carvalho Chehab /* unused */ 1450c0d06caSMauro Carvalho Chehab } 1460c0d06caSMauro Carvalho Chehab 1470c0d06caSMauro Carvalho Chehab /* reception of an URB */ 1480c0d06caSMauro Carvalho Chehab static void sd_isoc_irq(struct urb *urb) 1490c0d06caSMauro Carvalho Chehab { 1500c0d06caSMauro Carvalho Chehab struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; 1510c0d06caSMauro Carvalho Chehab struct urb *urb0; 1520c0d06caSMauro Carvalho Chehab u8 *data; 1530c0d06caSMauro Carvalho Chehab int i, st; 1540c0d06caSMauro Carvalho Chehab 15537d5efb0SJoe Perches gspca_dbg(gspca_dev, D_PACK, "sd isoc irq\n"); 1560c0d06caSMauro Carvalho Chehab if (!gspca_dev->streaming) 1570c0d06caSMauro Carvalho Chehab return; 1580c0d06caSMauro Carvalho Chehab if (urb->status != 0) { 1590c0d06caSMauro Carvalho Chehab if (urb->status == -ESHUTDOWN) 1600c0d06caSMauro Carvalho Chehab return; /* disconnection */ 1610c0d06caSMauro Carvalho Chehab #ifdef CONFIG_PM 1620c0d06caSMauro Carvalho Chehab if (gspca_dev->frozen) 1630c0d06caSMauro Carvalho Chehab return; 1640c0d06caSMauro Carvalho Chehab #endif 1650c0d06caSMauro Carvalho Chehab pr_err("urb status: %d\n", urb->status); 1660c0d06caSMauro Carvalho Chehab return; 1670c0d06caSMauro Carvalho Chehab } 1680c0d06caSMauro Carvalho Chehab 1690c0d06caSMauro Carvalho Chehab /* if this is a control URN (ep 0x83), wait */ 1700c0d06caSMauro Carvalho Chehab if (urb == gspca_dev->urb[0] || urb == gspca_dev->urb[2]) 1710c0d06caSMauro Carvalho Chehab return; 1720c0d06caSMauro Carvalho Chehab 1730c0d06caSMauro Carvalho Chehab /* scan both received URBs */ 1740c0d06caSMauro Carvalho Chehab if (urb == gspca_dev->urb[1]) 1750c0d06caSMauro Carvalho Chehab urb0 = gspca_dev->urb[0]; 1760c0d06caSMauro Carvalho Chehab else 1770c0d06caSMauro Carvalho Chehab urb0 = gspca_dev->urb[2]; 1780c0d06caSMauro Carvalho Chehab for (i = 0; i < urb->number_of_packets; i++) { 1790c0d06caSMauro Carvalho Chehab 1800c0d06caSMauro Carvalho Chehab /* check the packet status and length */ 1810c0d06caSMauro Carvalho Chehab if (urb0->iso_frame_desc[i].actual_length != SD_PKT_SZ 1820c0d06caSMauro Carvalho Chehab || urb->iso_frame_desc[i].actual_length != SD_PKT_SZ) { 18352173c5fSJoe Perches gspca_err(gspca_dev, "ISOC bad lengths %d / %d\n", 1840c0d06caSMauro Carvalho Chehab urb0->iso_frame_desc[i].actual_length, 1850c0d06caSMauro Carvalho Chehab urb->iso_frame_desc[i].actual_length); 1860c0d06caSMauro Carvalho Chehab gspca_dev->last_packet_type = DISCARD_PACKET; 1870c0d06caSMauro Carvalho Chehab continue; 1880c0d06caSMauro Carvalho Chehab } 1890c0d06caSMauro Carvalho Chehab st = urb0->iso_frame_desc[i].status; 1900c0d06caSMauro Carvalho Chehab if (st == 0) 1910c0d06caSMauro Carvalho Chehab st = urb->iso_frame_desc[i].status; 1920c0d06caSMauro Carvalho Chehab if (st) { 1930c0d06caSMauro Carvalho Chehab pr_err("ISOC data error: [%d] status=%d\n", 1940c0d06caSMauro Carvalho Chehab i, st); 1950c0d06caSMauro Carvalho Chehab gspca_dev->last_packet_type = DISCARD_PACKET; 1960c0d06caSMauro Carvalho Chehab continue; 1970c0d06caSMauro Carvalho Chehab } 1980c0d06caSMauro Carvalho Chehab 1990c0d06caSMauro Carvalho Chehab /* 2000c0d06caSMauro Carvalho Chehab * The images are received in URBs of different endpoints 2010c0d06caSMauro Carvalho Chehab * (0x83 and 0x82). 2020c0d06caSMauro Carvalho Chehab * Image pieces in URBs of ep 0x83 are continuated in URBs of 2030c0d06caSMauro Carvalho Chehab * ep 0x82 of the same index. 2040c0d06caSMauro Carvalho Chehab * The packets in the URBs of endpoint 0x83 start with: 2050c0d06caSMauro Carvalho Chehab * - 80 ba/bb 00 00 = start of image followed by 'ff d8' 2060c0d06caSMauro Carvalho Chehab * - 04 ba/bb oo oo = image piece 2070c0d06caSMauro Carvalho Chehab * where 'oo oo' is the image offset 2083e4d8f48SMauro Carvalho Chehab (not checked) 2090c0d06caSMauro Carvalho Chehab * - (other -> bad frame) 2100c0d06caSMauro Carvalho Chehab * The images are JPEG encoded with full header and 2110c0d06caSMauro Carvalho Chehab * normal ff escape. 2120c0d06caSMauro Carvalho Chehab * The end of image ('ff d9') may occur in any URB. 2133e4d8f48SMauro Carvalho Chehab * (not checked) 2140c0d06caSMauro Carvalho Chehab */ 2150c0d06caSMauro Carvalho Chehab data = (u8 *) urb0->transfer_buffer 2160c0d06caSMauro Carvalho Chehab + urb0->iso_frame_desc[i].offset; 2170c0d06caSMauro Carvalho Chehab if (data[0] == 0x80 && (data[1] & 0xfe) == 0xba) { 2180c0d06caSMauro Carvalho Chehab 2190c0d06caSMauro Carvalho Chehab /* new image */ 2200c0d06caSMauro Carvalho Chehab gspca_frame_add(gspca_dev, LAST_PACKET, 2210c0d06caSMauro Carvalho Chehab NULL, 0); 2220c0d06caSMauro Carvalho Chehab gspca_frame_add(gspca_dev, FIRST_PACKET, 2230c0d06caSMauro Carvalho Chehab data + 4, SD_PKT_SZ - 4); 2240c0d06caSMauro Carvalho Chehab } else if (data[0] == 0x04 && (data[1] & 0xfe) == 0xba) { 2250c0d06caSMauro Carvalho Chehab gspca_frame_add(gspca_dev, INTER_PACKET, 2260c0d06caSMauro Carvalho Chehab data + 4, SD_PKT_SZ - 4); 2270c0d06caSMauro Carvalho Chehab } else { 2280c0d06caSMauro Carvalho Chehab gspca_dev->last_packet_type = DISCARD_PACKET; 2290c0d06caSMauro Carvalho Chehab continue; 2300c0d06caSMauro Carvalho Chehab } 2310c0d06caSMauro Carvalho Chehab data = (u8 *) urb->transfer_buffer 2320c0d06caSMauro Carvalho Chehab + urb->iso_frame_desc[i].offset; 2330c0d06caSMauro Carvalho Chehab gspca_frame_add(gspca_dev, INTER_PACKET, 2340c0d06caSMauro Carvalho Chehab data, SD_PKT_SZ); 2350c0d06caSMauro Carvalho Chehab } 2360c0d06caSMauro Carvalho Chehab 2370c0d06caSMauro Carvalho Chehab /* resubmit the URBs */ 2380c0d06caSMauro Carvalho Chehab st = usb_submit_urb(urb0, GFP_ATOMIC); 2390c0d06caSMauro Carvalho Chehab if (st < 0) 2400c0d06caSMauro Carvalho Chehab pr_err("usb_submit_urb(0) ret %d\n", st); 2410c0d06caSMauro Carvalho Chehab st = usb_submit_urb(urb, GFP_ATOMIC); 2420c0d06caSMauro Carvalho Chehab if (st < 0) 2430c0d06caSMauro Carvalho Chehab pr_err("usb_submit_urb() ret %d\n", st); 2440c0d06caSMauro Carvalho Chehab } 2450c0d06caSMauro Carvalho Chehab 2460c0d06caSMauro Carvalho Chehab /* sub-driver description */ 2470c0d06caSMauro Carvalho Chehab static const struct sd_desc sd_desc = { 2480c0d06caSMauro Carvalho Chehab .name = MODULE_NAME, 2490c0d06caSMauro Carvalho Chehab .config = sd_config, 2500c0d06caSMauro Carvalho Chehab .init = sd_init, 2510c0d06caSMauro Carvalho Chehab .start = sd_start, 2520c0d06caSMauro Carvalho Chehab .stopN = sd_stopN, 2530c0d06caSMauro Carvalho Chehab .pkt_scan = sd_pkt_scan, 2540c0d06caSMauro Carvalho Chehab }; 2550c0d06caSMauro Carvalho Chehab 2560c0d06caSMauro Carvalho Chehab /* -- module initialisation -- */ 2570c0d06caSMauro Carvalho Chehab static const struct usb_device_id device_table[] = { 2580c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x04a5, 0x3035)}, 2590c0d06caSMauro Carvalho Chehab {} 2600c0d06caSMauro Carvalho Chehab }; 2610c0d06caSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, device_table); 2620c0d06caSMauro Carvalho Chehab 2630c0d06caSMauro Carvalho Chehab /* -- device connect -- */ 2640c0d06caSMauro Carvalho Chehab static int sd_probe(struct usb_interface *intf, 2650c0d06caSMauro Carvalho Chehab const struct usb_device_id *id) 2660c0d06caSMauro Carvalho Chehab { 2670c0d06caSMauro Carvalho Chehab return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 2680c0d06caSMauro Carvalho Chehab THIS_MODULE); 2690c0d06caSMauro Carvalho Chehab } 2700c0d06caSMauro Carvalho Chehab 2710c0d06caSMauro Carvalho Chehab static struct usb_driver sd_driver = { 2720c0d06caSMauro Carvalho Chehab .name = MODULE_NAME, 2730c0d06caSMauro Carvalho Chehab .id_table = device_table, 2740c0d06caSMauro Carvalho Chehab .probe = sd_probe, 2750c0d06caSMauro Carvalho Chehab .disconnect = gspca_disconnect, 2760c0d06caSMauro Carvalho Chehab #ifdef CONFIG_PM 2770c0d06caSMauro Carvalho Chehab .suspend = gspca_suspend, 2780c0d06caSMauro Carvalho Chehab .resume = gspca_resume, 2790c0d06caSMauro Carvalho Chehab .reset_resume = gspca_resume, 2800c0d06caSMauro Carvalho Chehab #endif 2810c0d06caSMauro Carvalho Chehab }; 2820c0d06caSMauro Carvalho Chehab 2830c0d06caSMauro Carvalho Chehab module_usb_driver(sd_driver); 284