Path: blob/master/drivers/media/video/cpia2/cpia2_usb.c
17621 views
/****************************************************************************1*2* Filename: cpia2_usb.c3*4* Copyright 2001, STMicrolectronics, Inc.5* Contact: [email protected]6*7* Description:8* This is a USB driver for CPia2 based video cameras.9* The infrastructure of this driver is based on the cpia usb driver by10* Jochen Scharrlach and Johannes Erdfeldt.11*12* This program is free software; you can redistribute it and/or modify13* it under the terms of the GNU General Public License as published by14* the Free Software Foundation; either version 2 of the License, or15* (at your option) any later version.16*17* This program is distributed in the hope that it will be useful,18* but WITHOUT ANY WARRANTY; without even the implied warranty of19* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the20* GNU General Public License for more details.21*22* You should have received a copy of the GNU General Public License23* along with this program; if not, write to the Free Software24* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.25*26* Stripped of 2.4 stuff ready for main kernel submit by27* Alan Cox <[email protected]>28****************************************************************************/2930#include <linux/kernel.h>31#include <linux/slab.h>32#include <linux/usb.h>3334#include "cpia2.h"3536static int frame_sizes[] = {370, // USBIF_CMDONLY380, // USBIF_BULK39128, // USBIF_ISO_140384, // USBIF_ISO_241640, // USBIF_ISO_342768, // USBIF_ISO_443896, // USBIF_ISO_5441023, // USBIF_ISO_645};4647#define FRAMES_PER_DESC 1048#define FRAME_SIZE_PER_DESC frame_sizes[cam->cur_alt]4950static void process_frame(struct camera_data *cam);51static void cpia2_usb_complete(struct urb *urb);52static int cpia2_usb_probe(struct usb_interface *intf,53const struct usb_device_id *id);54static void cpia2_usb_disconnect(struct usb_interface *intf);5556static void free_sbufs(struct camera_data *cam);57static void add_APPn(struct camera_data *cam);58static void add_COM(struct camera_data *cam);59static int submit_urbs(struct camera_data *cam);60static int set_alternate(struct camera_data *cam, unsigned int alt);61static int configure_transfer_mode(struct camera_data *cam, unsigned int alt);6263static struct usb_device_id cpia2_id_table[] = {64{USB_DEVICE(0x0553, 0x0100)},65{USB_DEVICE(0x0553, 0x0140)},66{USB_DEVICE(0x0553, 0x0151)}, /* STV0676 */67{} /* Terminating entry */68};69MODULE_DEVICE_TABLE(usb, cpia2_id_table);7071static struct usb_driver cpia2_driver = {72.name = "cpia2",73.probe = cpia2_usb_probe,74.disconnect = cpia2_usb_disconnect,75.id_table = cpia2_id_table76};777879/******************************************************************************80*81* process_frame82*83*****************************************************************************/84static void process_frame(struct camera_data *cam)85{86static int frame_count;8788unsigned char *inbuff = cam->workbuff->data;8990DBG("Processing frame #%d, current:%d\n",91cam->workbuff->num, cam->curbuff->num);9293if(cam->workbuff->length > cam->workbuff->max_length)94cam->workbuff->max_length = cam->workbuff->length;9596if ((inbuff[0] == 0xFF) && (inbuff[1] == 0xD8)) {97frame_count++;98} else {99cam->workbuff->status = FRAME_ERROR;100DBG("Start of frame not found\n");101return;102}103104/***105* Now the output buffer should have a JPEG image in it.106***/107if(!cam->first_image_seen) {108/* Always skip the first image after streaming109* starts. It is almost certainly corrupt. */110cam->first_image_seen = 1;111cam->workbuff->status = FRAME_EMPTY;112return;113}114if (cam->workbuff->length > 3) {115if(cam->mmapped &&116cam->workbuff->length < cam->workbuff->max_length) {117/* No junk in the buffers */118memset(cam->workbuff->data+cam->workbuff->length,1190, cam->workbuff->max_length-120cam->workbuff->length);121}122cam->workbuff->max_length = cam->workbuff->length;123cam->workbuff->status = FRAME_READY;124125if(!cam->mmapped && cam->num_frames > 2) {126/* During normal reading, the most recent127* frame will be read. If the current frame128* hasn't started reading yet, it will never129* be read, so mark it empty. If the buffer is130* mmapped, or we have few buffers, we need to131* wait for the user to free the buffer.132*133* NOTE: This is not entirely foolproof with 3134* buffers, but it would take an EXTREMELY135* overloaded system to cause problems (possible136* image data corruption). Basically, it would137* need to take more time to execute cpia2_read138* than it would for the camera to send139* cam->num_frames-2 frames before problems140* could occur.141*/142cam->curbuff->status = FRAME_EMPTY;143}144cam->curbuff = cam->workbuff;145cam->workbuff = cam->workbuff->next;146DBG("Changed buffers, work:%d, current:%d\n",147cam->workbuff->num, cam->curbuff->num);148return;149} else {150DBG("Not enough data for an image.\n");151}152153cam->workbuff->status = FRAME_ERROR;154return;155}156157/******************************************************************************158*159* add_APPn160*161* Adds a user specified APPn record162*****************************************************************************/163static void add_APPn(struct camera_data *cam)164{165if(cam->APP_len > 0) {166cam->workbuff->data[cam->workbuff->length++] = 0xFF;167cam->workbuff->data[cam->workbuff->length++] = 0xE0+cam->APPn;168cam->workbuff->data[cam->workbuff->length++] = 0;169cam->workbuff->data[cam->workbuff->length++] = cam->APP_len+2;170memcpy(cam->workbuff->data+cam->workbuff->length,171cam->APP_data, cam->APP_len);172cam->workbuff->length += cam->APP_len;173}174}175176/******************************************************************************177*178* add_COM179*180* Adds a user specified COM record181*****************************************************************************/182static void add_COM(struct camera_data *cam)183{184if(cam->COM_len > 0) {185cam->workbuff->data[cam->workbuff->length++] = 0xFF;186cam->workbuff->data[cam->workbuff->length++] = 0xFE;187cam->workbuff->data[cam->workbuff->length++] = 0;188cam->workbuff->data[cam->workbuff->length++] = cam->COM_len+2;189memcpy(cam->workbuff->data+cam->workbuff->length,190cam->COM_data, cam->COM_len);191cam->workbuff->length += cam->COM_len;192}193}194195/******************************************************************************196*197* cpia2_usb_complete198*199* callback when incoming packet is received200*****************************************************************************/201static void cpia2_usb_complete(struct urb *urb)202{203int i;204unsigned char *cdata;205static int frame_ready = false;206struct camera_data *cam = (struct camera_data *) urb->context;207208if (urb->status!=0) {209if (!(urb->status == -ENOENT ||210urb->status == -ECONNRESET ||211urb->status == -ESHUTDOWN))212{213DBG("urb->status = %d!\n", urb->status);214}215DBG("Stopping streaming\n");216return;217}218219if (!cam->streaming || !cam->present || cam->open_count == 0) {220LOG("Will now stop the streaming: streaming = %d, "221"present=%d, open_count=%d\n",222cam->streaming, cam->present, cam->open_count);223return;224}225226/***227* Packet collater228***/229//DBG("Collating %d packets\n", urb->number_of_packets);230for (i = 0; i < urb->number_of_packets; i++) {231u16 checksum, iso_checksum;232int j;233int n = urb->iso_frame_desc[i].actual_length;234int st = urb->iso_frame_desc[i].status;235236if(cam->workbuff->status == FRAME_READY) {237struct framebuf *ptr;238/* Try to find an available buffer */239DBG("workbuff full, searching\n");240for (ptr = cam->workbuff->next;241ptr != cam->workbuff;242ptr = ptr->next)243{244if (ptr->status == FRAME_EMPTY) {245ptr->status = FRAME_READING;246ptr->length = 0;247break;248}249}250if (ptr == cam->workbuff)251break; /* No READING or EMPTY buffers left */252253cam->workbuff = ptr;254}255256if (cam->workbuff->status == FRAME_EMPTY ||257cam->workbuff->status == FRAME_ERROR) {258cam->workbuff->status = FRAME_READING;259cam->workbuff->length = 0;260}261262//DBG(" Packet %d length = %d, status = %d\n", i, n, st);263cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;264265if (st) {266LOG("cpia2 data error: [%d] len=%d, status = %d\n",267i, n, st);268if(!ALLOW_CORRUPT)269cam->workbuff->status = FRAME_ERROR;270continue;271}272273if(n<=2)274continue;275276checksum = 0;277for(j=0; j<n-2; ++j)278checksum += cdata[j];279iso_checksum = cdata[j] + cdata[j+1]*256;280if(checksum != iso_checksum) {281LOG("checksum mismatch: [%d] len=%d, calculated = %x, checksum = %x\n",282i, n, (int)checksum, (int)iso_checksum);283if(!ALLOW_CORRUPT) {284cam->workbuff->status = FRAME_ERROR;285continue;286}287}288n -= 2;289290if(cam->workbuff->status != FRAME_READING) {291if((0xFF == cdata[0] && 0xD8 == cdata[1]) ||292(0xD8 == cdata[0] && 0xFF == cdata[1] &&2930 != cdata[2])) {294/* frame is skipped, but increment total295* frame count anyway */296cam->frame_count++;297}298DBG("workbuff not reading, status=%d\n",299cam->workbuff->status);300continue;301}302303if (cam->frame_size < cam->workbuff->length + n) {304ERR("buffer overflow! length: %d, n: %d\n",305cam->workbuff->length, n);306cam->workbuff->status = FRAME_ERROR;307if(cam->workbuff->length > cam->workbuff->max_length)308cam->workbuff->max_length =309cam->workbuff->length;310continue;311}312313if (cam->workbuff->length == 0) {314int data_offset;315if ((0xD8 == cdata[0]) && (0xFF == cdata[1])) {316data_offset = 1;317} else if((0xFF == cdata[0]) && (0xD8 == cdata[1])318&& (0xFF == cdata[2])) {319data_offset = 2;320} else {321DBG("Ignoring packet, not beginning!\n");322continue;323}324DBG("Start of frame pattern found\n");325do_gettimeofday(&cam->workbuff->timestamp);326cam->workbuff->seq = cam->frame_count++;327cam->workbuff->data[0] = 0xFF;328cam->workbuff->data[1] = 0xD8;329cam->workbuff->length = 2;330add_APPn(cam);331add_COM(cam);332memcpy(cam->workbuff->data+cam->workbuff->length,333cdata+data_offset, n-data_offset);334cam->workbuff->length += n-data_offset;335} else if (cam->workbuff->length > 0) {336memcpy(cam->workbuff->data + cam->workbuff->length,337cdata, n);338cam->workbuff->length += n;339}340341if ((cam->workbuff->length >= 3) &&342(cam->workbuff->data[cam->workbuff->length - 3] == 0xFF) &&343(cam->workbuff->data[cam->workbuff->length - 2] == 0xD9) &&344(cam->workbuff->data[cam->workbuff->length - 1] == 0xFF)) {345frame_ready = true;346cam->workbuff->data[cam->workbuff->length - 1] = 0;347cam->workbuff->length -= 1;348} else if ((cam->workbuff->length >= 2) &&349(cam->workbuff->data[cam->workbuff->length - 2] == 0xFF) &&350(cam->workbuff->data[cam->workbuff->length - 1] == 0xD9)) {351frame_ready = true;352}353354if (frame_ready) {355DBG("Workbuff image size = %d\n",cam->workbuff->length);356process_frame(cam);357358frame_ready = false;359360if (waitqueue_active(&cam->wq_stream))361wake_up_interruptible(&cam->wq_stream);362}363}364365if(cam->streaming) {366/* resubmit */367urb->dev = cam->dev;368if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)369ERR("%s: usb_submit_urb ret %d!\n", __func__, i);370}371}372373/******************************************************************************374*375* configure_transfer_mode376*377*****************************************************************************/378static int configure_transfer_mode(struct camera_data *cam, unsigned int alt)379{380static unsigned char iso_regs[8][4] = {381{0x00, 0x00, 0x00, 0x00},382{0x00, 0x00, 0x00, 0x00},383{0xB9, 0x00, 0x00, 0x7E},384{0xB9, 0x00, 0x01, 0x7E},385{0xB9, 0x00, 0x02, 0x7E},386{0xB9, 0x00, 0x02, 0xFE},387{0xB9, 0x00, 0x03, 0x7E},388{0xB9, 0x00, 0x03, 0xFD}389};390struct cpia2_command cmd;391unsigned char reg;392393if(!cam->present)394return -ENODEV;395396/***397* Write the isoc registers according to the alternate selected398***/399cmd.direction = TRANSFER_WRITE;400cmd.buffer.block_data[0] = iso_regs[alt][0];401cmd.buffer.block_data[1] = iso_regs[alt][1];402cmd.buffer.block_data[2] = iso_regs[alt][2];403cmd.buffer.block_data[3] = iso_regs[alt][3];404cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;405cmd.start = CPIA2_VC_USB_ISOLIM;406cmd.reg_count = 4;407cpia2_send_command(cam, &cmd);408409/***410* Enable relevant streams before starting polling.411* First read USB Stream Config Register.412***/413cmd.direction = TRANSFER_READ;414cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;415cmd.start = CPIA2_VC_USB_STRM;416cmd.reg_count = 1;417cpia2_send_command(cam, &cmd);418reg = cmd.buffer.block_data[0];419420/* Clear iso, bulk, and int */421reg &= ~(CPIA2_VC_USB_STRM_BLK_ENABLE |422CPIA2_VC_USB_STRM_ISO_ENABLE |423CPIA2_VC_USB_STRM_INT_ENABLE);424425if (alt == USBIF_BULK) {426DBG("Enabling bulk xfer\n");427reg |= CPIA2_VC_USB_STRM_BLK_ENABLE; /* Enable Bulk */428cam->xfer_mode = XFER_BULK;429} else if (alt >= USBIF_ISO_1) {430DBG("Enabling ISOC xfer\n");431reg |= CPIA2_VC_USB_STRM_ISO_ENABLE;432cam->xfer_mode = XFER_ISOC;433}434435cmd.buffer.block_data[0] = reg;436cmd.direction = TRANSFER_WRITE;437cmd.start = CPIA2_VC_USB_STRM;438cmd.reg_count = 1;439cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;440cpia2_send_command(cam, &cmd);441442return 0;443}444445/******************************************************************************446*447* cpia2_usb_change_streaming_alternate448*449*****************************************************************************/450int cpia2_usb_change_streaming_alternate(struct camera_data *cam,451unsigned int alt)452{453int ret = 0;454455if(alt < USBIF_ISO_1 || alt > USBIF_ISO_6)456return -EINVAL;457458if(alt == cam->params.camera_state.stream_mode)459return 0;460461cpia2_usb_stream_pause(cam);462463configure_transfer_mode(cam, alt);464465cam->params.camera_state.stream_mode = alt;466467/* Reset the camera to prevent image quality degradation */468cpia2_reset_camera(cam);469470cpia2_usb_stream_resume(cam);471472return ret;473}474475/******************************************************************************476*477* set_alternate478*479*****************************************************************************/480static int set_alternate(struct camera_data *cam, unsigned int alt)481{482int ret = 0;483484if(alt == cam->cur_alt)485return 0;486487if (cam->cur_alt != USBIF_CMDONLY) {488DBG("Changing from alt %d to %d\n", cam->cur_alt, USBIF_CMDONLY);489ret = usb_set_interface(cam->dev, cam->iface, USBIF_CMDONLY);490if (ret != 0)491return ret;492}493if (alt != USBIF_CMDONLY) {494DBG("Changing from alt %d to %d\n", USBIF_CMDONLY, alt);495ret = usb_set_interface(cam->dev, cam->iface, alt);496if (ret != 0)497return ret;498}499500cam->old_alt = cam->cur_alt;501cam->cur_alt = alt;502503return ret;504}505506/******************************************************************************507*508* free_sbufs509*510* Free all cam->sbuf[]. All non-NULL .data and .urb members that are non-NULL511* are assumed to be allocated. Non-NULL .urb members are also assumed to be512* submitted (and must therefore be killed before they are freed).513*****************************************************************************/514static void free_sbufs(struct camera_data *cam)515{516int i;517518for (i = 0; i < NUM_SBUF; i++) {519if(cam->sbuf[i].urb) {520usb_kill_urb(cam->sbuf[i].urb);521usb_free_urb(cam->sbuf[i].urb);522cam->sbuf[i].urb = NULL;523}524if(cam->sbuf[i].data) {525kfree(cam->sbuf[i].data);526cam->sbuf[i].data = NULL;527}528}529}530531/*******532* Convenience functions533*******/534/****************************************************************************535*536* write_packet537*538***************************************************************************/539static int write_packet(struct usb_device *udev,540u8 request, u8 * registers, u16 start, size_t size)541{542if (!registers || size <= 0)543return -EINVAL;544545return usb_control_msg(udev,546usb_sndctrlpipe(udev, 0),547request,548USB_TYPE_VENDOR | USB_RECIP_DEVICE,549start, /* value */5500, /* index */551registers, /* buffer */552size,553HZ);554}555556/****************************************************************************557*558* read_packet559*560***************************************************************************/561static int read_packet(struct usb_device *udev,562u8 request, u8 * registers, u16 start, size_t size)563{564if (!registers || size <= 0)565return -EINVAL;566567return usb_control_msg(udev,568usb_rcvctrlpipe(udev, 0),569request,570USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE,571start, /* value */5720, /* index */573registers, /* buffer */574size,575HZ);576}577578/******************************************************************************579*580* cpia2_usb_transfer_cmd581*582*****************************************************************************/583int cpia2_usb_transfer_cmd(struct camera_data *cam,584void *registers,585u8 request, u8 start, u8 count, u8 direction)586{587int err = 0;588struct usb_device *udev = cam->dev;589590if (!udev) {591ERR("%s: Internal driver error: udev is NULL\n", __func__);592return -EINVAL;593}594595if (!registers) {596ERR("%s: Internal driver error: register array is NULL\n", __func__);597return -EINVAL;598}599600if (direction == TRANSFER_READ) {601err = read_packet(udev, request, (u8 *)registers, start, count);602if (err > 0)603err = 0;604} else if (direction == TRANSFER_WRITE) {605err =write_packet(udev, request, (u8 *)registers, start, count);606if (err < 0) {607LOG("Control message failed, err val = %d\n", err);608LOG("Message: request = 0x%0X, start = 0x%0X\n",609request, start);610LOG("Message: count = %d, register[0] = 0x%0X\n",611count, ((unsigned char *) registers)[0]);612} else613err=0;614} else {615LOG("Unexpected first byte of direction: %d\n",616direction);617return -EINVAL;618}619620if(err != 0)621LOG("Unexpected error: %d\n", err);622return err;623}624625626/******************************************************************************627*628* submit_urbs629*630*****************************************************************************/631static int submit_urbs(struct camera_data *cam)632{633struct urb *urb;634int fx, err, i, j;635636for(i=0; i<NUM_SBUF; ++i) {637if (cam->sbuf[i].data)638continue;639cam->sbuf[i].data =640kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);641if (!cam->sbuf[i].data) {642while (--i >= 0) {643kfree(cam->sbuf[i].data);644cam->sbuf[i].data = NULL;645}646return -ENOMEM;647}648}649650/* We double buffer the Isoc lists, and also know the polling651* interval is every frame (1 == (1 << (bInterval -1))).652*/653for(i=0; i<NUM_SBUF; ++i) {654if(cam->sbuf[i].urb) {655continue;656}657urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);658if (!urb) {659ERR("%s: usb_alloc_urb error!\n", __func__);660for (j = 0; j < i; j++)661usb_free_urb(cam->sbuf[j].urb);662return -ENOMEM;663}664665cam->sbuf[i].urb = urb;666urb->dev = cam->dev;667urb->context = cam;668urb->pipe = usb_rcvisocpipe(cam->dev, 1 /*ISOC endpoint*/);669urb->transfer_flags = URB_ISO_ASAP;670urb->transfer_buffer = cam->sbuf[i].data;671urb->complete = cpia2_usb_complete;672urb->number_of_packets = FRAMES_PER_DESC;673urb->interval = 1;674urb->transfer_buffer_length =675FRAME_SIZE_PER_DESC * FRAMES_PER_DESC;676677for (fx = 0; fx < FRAMES_PER_DESC; fx++) {678urb->iso_frame_desc[fx].offset =679FRAME_SIZE_PER_DESC * fx;680urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC;681}682}683684685/* Queue the ISO urbs, and resubmit in the completion handler */686for(i=0; i<NUM_SBUF; ++i) {687err = usb_submit_urb(cam->sbuf[i].urb, GFP_KERNEL);688if (err) {689ERR("usb_submit_urb[%d]() = %d\n", i, err);690return err;691}692}693694return 0;695}696697/******************************************************************************698*699* cpia2_usb_stream_start700*701*****************************************************************************/702int cpia2_usb_stream_start(struct camera_data *cam, unsigned int alternate)703{704int ret;705int old_alt;706707if(cam->streaming)708return 0;709710if (cam->flush) {711int i;712DBG("Flushing buffers\n");713for(i=0; i<cam->num_frames; ++i) {714cam->buffers[i].status = FRAME_EMPTY;715cam->buffers[i].length = 0;716}717cam->curbuff = &cam->buffers[0];718cam->workbuff = cam->curbuff->next;719cam->flush = false;720}721722old_alt = cam->params.camera_state.stream_mode;723cam->params.camera_state.stream_mode = 0;724ret = cpia2_usb_change_streaming_alternate(cam, alternate);725if (ret < 0) {726int ret2;727ERR("cpia2_usb_change_streaming_alternate() = %d!\n", ret);728cam->params.camera_state.stream_mode = old_alt;729ret2 = set_alternate(cam, USBIF_CMDONLY);730if (ret2 < 0) {731ERR("cpia2_usb_change_streaming_alternate(%d) =%d has already "732"failed. Then tried to call "733"set_alternate(USBIF_CMDONLY) = %d.\n",734alternate, ret, ret2);735}736} else {737cam->frame_count = 0;738cam->streaming = 1;739ret = cpia2_usb_stream_resume(cam);740}741return ret;742}743744/******************************************************************************745*746* cpia2_usb_stream_pause747*748*****************************************************************************/749int cpia2_usb_stream_pause(struct camera_data *cam)750{751int ret = 0;752if(cam->streaming) {753ret = set_alternate(cam, USBIF_CMDONLY);754free_sbufs(cam);755}756return ret;757}758759/******************************************************************************760*761* cpia2_usb_stream_resume762*763*****************************************************************************/764int cpia2_usb_stream_resume(struct camera_data *cam)765{766int ret = 0;767if(cam->streaming) {768cam->first_image_seen = 0;769ret = set_alternate(cam, cam->params.camera_state.stream_mode);770if(ret == 0) {771ret = submit_urbs(cam);772}773}774return ret;775}776777/******************************************************************************778*779* cpia2_usb_stream_stop780*781*****************************************************************************/782int cpia2_usb_stream_stop(struct camera_data *cam)783{784int ret;785ret = cpia2_usb_stream_pause(cam);786cam->streaming = 0;787configure_transfer_mode(cam, 0);788return ret;789}790791/******************************************************************************792*793* cpia2_usb_probe794*795* Probe and initialize.796*****************************************************************************/797static int cpia2_usb_probe(struct usb_interface *intf,798const struct usb_device_id *id)799{800struct usb_device *udev = interface_to_usbdev(intf);801struct usb_interface_descriptor *interface;802struct camera_data *cam;803int ret;804805/* A multi-config CPiA2 camera? */806if (udev->descriptor.bNumConfigurations != 1)807return -ENODEV;808interface = &intf->cur_altsetting->desc;809810/* If we get to this point, we found a CPiA2 camera */811LOG("CPiA2 USB camera found\n");812813if((cam = cpia2_init_camera_struct()) == NULL)814return -ENOMEM;815816cam->dev = udev;817cam->iface = interface->bInterfaceNumber;818819ret = set_alternate(cam, USBIF_CMDONLY);820if (ret < 0) {821ERR("%s: usb_set_interface error (ret = %d)\n", __func__, ret);822kfree(cam);823return ret;824}825826if ((ret = cpia2_register_camera(cam)) < 0) {827ERR("%s: Failed to register cpia2 camera (ret = %d)\n", __func__, ret);828kfree(cam);829return ret;830}831832833if((ret = cpia2_init_camera(cam)) < 0) {834ERR("%s: failed to initialize cpia2 camera (ret = %d)\n", __func__, ret);835cpia2_unregister_camera(cam);836kfree(cam);837return ret;838}839LOG(" CPiA Version: %d.%02d (%d.%d)\n",840cam->params.version.firmware_revision_hi,841cam->params.version.firmware_revision_lo,842cam->params.version.asic_id,843cam->params.version.asic_rev);844LOG(" CPiA PnP-ID: %04x:%04x:%04x\n",845cam->params.pnp_id.vendor,846cam->params.pnp_id.product,847cam->params.pnp_id.device_revision);848LOG(" SensorID: %d.(version %d)\n",849cam->params.version.sensor_flags,850cam->params.version.sensor_rev);851852usb_set_intfdata(intf, cam);853854return 0;855}856857/******************************************************************************858*859* cpia2_disconnect860*861*****************************************************************************/862static void cpia2_usb_disconnect(struct usb_interface *intf)863{864struct camera_data *cam = usb_get_intfdata(intf);865usb_set_intfdata(intf, NULL);866cam->present = 0;867868DBG("Stopping stream\n");869cpia2_usb_stream_stop(cam);870871DBG("Unregistering camera\n");872cpia2_unregister_camera(cam);873874if(cam->buffers) {875DBG("Wakeup waiting processes\n");876cam->curbuff->status = FRAME_READY;877cam->curbuff->length = 0;878if (waitqueue_active(&cam->wq_stream))879wake_up_interruptible(&cam->wq_stream);880}881882DBG("Releasing interface\n");883usb_driver_release_interface(&cpia2_driver, intf);884885if (cam->open_count == 0) {886DBG("Freeing camera structure\n");887kfree(cam);888}889890LOG("CPiA2 camera disconnected.\n");891}892893894/******************************************************************************895*896* usb_cpia2_init897*898*****************************************************************************/899int cpia2_usb_init(void)900{901return usb_register(&cpia2_driver);902}903904/******************************************************************************905*906* usb_cpia_cleanup907*908*****************************************************************************/909void cpia2_usb_cleanup(void)910{911schedule_timeout(2 * HZ);912usb_deregister(&cpia2_driver);913}914915916