Path: blob/master/drivers/media/video/gspca/benq.c
17602 views
/*1* Benq DC E300 subdriver2*3* Copyright (C) 2009 Jean-Francois Moine (http://moinejf.free.fr)4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA18*/1920#define MODULE_NAME "benq"2122#include "gspca.h"2324MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");25MODULE_DESCRIPTION("Benq DC E300 USB Camera Driver");26MODULE_LICENSE("GPL");2728/* specific webcam descriptor */29struct sd {30struct gspca_dev gspca_dev; /* !! must be the first item */31};3233/* V4L2 controls supported by the driver */34static const struct ctrl sd_ctrls[] = {35};3637static const struct v4l2_pix_format vga_mode[] = {38{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,39.bytesperline = 320,40.sizeimage = 320 * 240 * 3 / 8 + 590,41.colorspace = V4L2_COLORSPACE_JPEG},42};4344static void sd_isoc_irq(struct urb *urb);4546/* -- write a register -- */47static void reg_w(struct gspca_dev *gspca_dev,48u16 value, u16 index)49{50struct usb_device *dev = gspca_dev->dev;51int ret;5253if (gspca_dev->usb_err < 0)54return;55ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),560x02,57USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,58value,59index,60NULL,610,62500);63if (ret < 0) {64err("reg_w err %d", ret);65gspca_dev->usb_err = ret;66}67}6869/* this function is called at probe time */70static int sd_config(struct gspca_dev *gspca_dev,71const struct usb_device_id *id)72{73gspca_dev->cam.cam_mode = vga_mode;74gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);75gspca_dev->cam.no_urb_create = 1;76gspca_dev->cam.reverse_alts = 1;77return 0;78}7980/* this function is called at probe and resume time */81static int sd_init(struct gspca_dev *gspca_dev)82{83return 0;84}8586static int sd_isoc_init(struct gspca_dev *gspca_dev)87{88int ret;8990ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface,91gspca_dev->nbalt - 1);92if (ret < 0) {93err("usb_set_interface failed");94return ret;95}96/* reg_w(gspca_dev, 0x0003, 0x0002); */97return 0;98}99100/* -- start the camera -- */101static int sd_start(struct gspca_dev *gspca_dev)102{103struct urb *urb;104int i, n;105106/* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */107#if MAX_NURBS < 4108#error "Not enough URBs in the gspca table"109#endif110#define SD_PKT_SZ 64111#define SD_NPKT 32112for (n = 0; n < 4; n++) {113urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);114if (!urb) {115err("usb_alloc_urb failed");116return -ENOMEM;117}118gspca_dev->urb[n] = urb;119urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,120SD_PKT_SZ * SD_NPKT,121GFP_KERNEL,122&urb->transfer_dma);123124if (urb->transfer_buffer == NULL) {125err("usb_alloc_coherent failed");126return -ENOMEM;127}128urb->dev = gspca_dev->dev;129urb->context = gspca_dev;130urb->transfer_buffer_length = SD_PKT_SZ * SD_NPKT;131urb->pipe = usb_rcvisocpipe(gspca_dev->dev,132n & 1 ? 0x82 : 0x83);133urb->transfer_flags = URB_ISO_ASAP134| URB_NO_TRANSFER_DMA_MAP;135urb->interval = 1;136urb->complete = sd_isoc_irq;137urb->number_of_packets = SD_NPKT;138for (i = 0; i < SD_NPKT; i++) {139urb->iso_frame_desc[i].length = SD_PKT_SZ;140urb->iso_frame_desc[i].offset = SD_PKT_SZ * i;141}142}143144return gspca_dev->usb_err;145}146147static void sd_stopN(struct gspca_dev *gspca_dev)148{149reg_w(gspca_dev, 0x003c, 0x0003);150reg_w(gspca_dev, 0x003c, 0x0004);151reg_w(gspca_dev, 0x003c, 0x0005);152reg_w(gspca_dev, 0x003c, 0x0006);153reg_w(gspca_dev, 0x003c, 0x0007);154usb_set_interface(gspca_dev->dev, gspca_dev->iface,155gspca_dev->nbalt - 1);156}157158static void sd_pkt_scan(struct gspca_dev *gspca_dev,159u8 *data, /* isoc packet */160int len) /* iso packet length */161{162/* unused */163}164165/* reception of an URB */166static void sd_isoc_irq(struct urb *urb)167{168struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;169struct urb *urb0;170u8 *data;171int i, st;172173PDEBUG(D_PACK, "sd isoc irq");174if (!gspca_dev->streaming)175return;176if (urb->status != 0) {177if (urb->status == -ESHUTDOWN)178return; /* disconnection */179#ifdef CONFIG_PM180if (gspca_dev->frozen)181return;182#endif183err("urb status: %d", urb->status);184return;185}186187/* if this is a control URN (ep 0x83), wait */188if (urb == gspca_dev->urb[0] || urb == gspca_dev->urb[2])189return;190191/* scan both received URBs */192if (urb == gspca_dev->urb[1])193urb0 = gspca_dev->urb[0];194else195urb0 = gspca_dev->urb[2];196for (i = 0; i < urb->number_of_packets; i++) {197198/* check the packet status and length */199if (urb0->iso_frame_desc[i].actual_length != SD_PKT_SZ200|| urb->iso_frame_desc[i].actual_length != SD_PKT_SZ) {201PDEBUG(D_ERR, "ISOC bad lengths %d / %d",202urb0->iso_frame_desc[i].actual_length,203urb->iso_frame_desc[i].actual_length);204gspca_dev->last_packet_type = DISCARD_PACKET;205continue;206}207st = urb0->iso_frame_desc[i].status;208if (st == 0)209st = urb->iso_frame_desc[i].status;210if (st) {211err("ISOC data error: [%d] status=%d",212i, st);213gspca_dev->last_packet_type = DISCARD_PACKET;214continue;215}216217/*218* The images are received in URBs of different endpoints219* (0x83 and 0x82).220* Image pieces in URBs of ep 0x83 are continuated in URBs of221* ep 0x82 of the same index.222* The packets in the URBs of endpoint 0x83 start with:223* - 80 ba/bb 00 00 = start of image followed by 'ff d8'224* - 04 ba/bb oo oo = image piece225* where 'oo oo' is the image offset226(not cheked)227* - (other -> bad frame)228* The images are JPEG encoded with full header and229* normal ff escape.230* The end of image ('ff d9') may occur in any URB.231* (not cheked)232*/233data = (u8 *) urb0->transfer_buffer234+ urb0->iso_frame_desc[i].offset;235if (data[0] == 0x80 && (data[1] & 0xfe) == 0xba) {236237/* new image */238gspca_frame_add(gspca_dev, LAST_PACKET,239NULL, 0);240gspca_frame_add(gspca_dev, FIRST_PACKET,241data + 4, SD_PKT_SZ - 4);242} else if (data[0] == 0x04 && (data[1] & 0xfe) == 0xba) {243gspca_frame_add(gspca_dev, INTER_PACKET,244data + 4, SD_PKT_SZ - 4);245} else {246gspca_dev->last_packet_type = DISCARD_PACKET;247continue;248}249data = (u8 *) urb->transfer_buffer250+ urb->iso_frame_desc[i].offset;251gspca_frame_add(gspca_dev, INTER_PACKET,252data, SD_PKT_SZ);253}254255/* resubmit the URBs */256st = usb_submit_urb(urb0, GFP_ATOMIC);257if (st < 0)258err("usb_submit_urb(0) ret %d", st);259st = usb_submit_urb(urb, GFP_ATOMIC);260if (st < 0)261err("usb_submit_urb() ret %d", st);262}263264/* sub-driver description */265static const struct sd_desc sd_desc = {266.name = MODULE_NAME,267.ctrls = sd_ctrls,268.nctrls = ARRAY_SIZE(sd_ctrls),269.config = sd_config,270.init = sd_init,271.isoc_init = sd_isoc_init,272.start = sd_start,273.stopN = sd_stopN,274.pkt_scan = sd_pkt_scan,275};276277/* -- module initialisation -- */278static const struct usb_device_id device_table[] = {279{USB_DEVICE(0x04a5, 0x3035)},280{}281};282MODULE_DEVICE_TABLE(usb, device_table);283284/* -- device connect -- */285static int sd_probe(struct usb_interface *intf,286const struct usb_device_id *id)287{288return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),289THIS_MODULE);290}291292static struct usb_driver sd_driver = {293.name = MODULE_NAME,294.id_table = device_table,295.probe = sd_probe,296.disconnect = gspca_disconnect,297#ifdef CONFIG_PM298.suspend = gspca_suspend,299.resume = gspca_resume,300#endif301};302303/* -- module insert / remove -- */304static int __init sd_mod_init(void)305{306return usb_register(&sd_driver);307}308static void __exit sd_mod_exit(void)309{310usb_deregister(&sd_driver);311}312313module_init(sd_mod_init);314module_exit(sd_mod_exit);315316317