[cpia] USB anyone?
Jochen Scharrlach
Jochen.Scharrlach@schwaben.de
Sun, 16 Jan 2000 22:18:55 +0100 (CET)
--Multipart_Sun_Jan_16_22:18:55_2000-1
Content-Type: text/plain; charset=US-ASCII
Peter Pregler writes:
> That is fine with me as long as it does not blur the destinction between cpia.c
> and cpia_XXX.c. I don't mind where internal structures are connected to. Can
> you show me some code?
My idea is to add an argument to cpia_register_camera(), so I can
stuff the driver-struct into the video_device->lowlevel much
sooner. What I am missing is a cpia_unregister_camera()!
I have added my first try on cpia_usb.c, so you can take a look at
it. DISCLAIMER: I am 99.999% sure that it won't even compile, it's
just the result of two Sunday afternoons of hacking. The hard job will
be to get it to work - I am not even sure if the logic is correct, the
USB-stack isn't very well documented :-/
Bye,
Jochen
--
new signature coming RSN (tm)
--Multipart_Sun_Jan_16_22:18:55_2000-1
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="cpia_usb.c"
Content-Transfer-Encoding: 7bit
#include <linux/config.h>
#include <linux/module.h>
#include <linux/cpia.h>
static int cpia_usb_open(int camnr, void **privdata);
static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata),
void *cbdata);
static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data);
static int cpia_usb_streamStart(void *privdata);
static int cpia_usb_streamStop(void *privdata);
static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock);
static int cpia_usb_close(void *privdata);
#define ABOUT "USB driver for Vision CPiA based cameras"
static struct cpia_camera_ops cpia_usb_ops =
{
cpia_usb_open,
cpia_usb_registerCallback,
cpia_usb_transferCmd,
cpia_usb_streamStart,
cpia_usb_streamStop,
cpia_usb_streamRead,
cpia_usb_close
};
struct cpia_sbuf {
char *data;
urb_t *urb;
};
struct usb_cpia {
/* Device structure */
struct usb_device *dev;
unsigned char iface;
struct wait_queue *wq_stream;
};
static int cpia_usb_open(int camnr, usb_cpia **privdata)
{
usb_cpia *cpia = NULL;
if (privdata == NULL)
return -EINVAL;
cpia = *privdata;
if (cpia == NULL)
return -EINVAL;
if (usb_set_interface(cpia->dev, cpia->iface, 3) < 0) {
printk(KERN_ERR "usb_set_interface error\n");
return -EBUSY;
}
return 0;
}
static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data)
{
int err;
int retval=0;
int databytes;
struct usb_device *cam = ((usb_cpia)privdata)->dev;
if(cam == NULL) {
DBG("Internal driver error: cam is NULL\n");
return -EINVAL;
}
if(command == NULL) {
DBG("Internal driver error: command is NULL\n");
return -EINVAL;
}
databytes = (((int)command[7])<<8) | command[6];
if(command[0] == DATA_IN) {
u8 buffer[8];
if(data == NULL) {
DBG("Internal driver error: data is NULL\n");
return -EINVAL;
}
err = ReadPacket(cam, command, buffer, 8);
if(err < 0) {
return err;
}
memcpy(data, buffer, databytes);
} else if(command[0] == DATA_OUT) {
WritePacket(cam, command);
}
} else {
DBG("Unexpected first byte of command: %x\n", command[0]);
retval = -EINVAL;
}
return retval;
}
static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata),
void *cbdata)
{
return -ENODEV;
}
static int cpia_usb_streamStart(void *privdata)
{
return -ENODEV;
}
static int cpia_usb_streamStop(void *privdata)
{
return -ENODEV;
}
static int cpia_usb_streamRead(usb_cpia *cpia, u8 *frame, int noblock)
{
int len = 0;
struct urb *urb = usb_alloc_urb(1);
if (!urb) {
printk(KERN_ERR "cpia_init_isoc: usb_init_isoc ret %d\n",
0);
return -ENOMEM;
}
FILL_BULK_URB(urb, cpia->dev, usb_rcvbulkpipe(cpia->dev, 1),
frame, CPIA_MAX_IMAGE_SIZE, cpia_usb_complete, cpia);
err = usb_submit_urb(urb);
if (err)
{
printk(KERN_ERR "cpia_init_isoc: usb_run_isoc(0) ret %d\n",
err);
return err;
}
interruptible_sleep_on(&cpia->wq_stream);
len = urb->actual_length;
usb_unlink_urb(urb);
usb_free_urb(urb);
return len;
}
static int cpia_usb_close(void *privdata)
{
return 0;
}
int cpia_usb_init(void)
{
/* return -ENODEV; */
return 0;
}
static void cpia_usb_complete(usb_cpia *cpia)
{
if (waitqueue_active(&cpia->wq_stream)) { /* FIXME */
wake_up(&cpia->wq_stream);
}
}
//
// convenience functions
//
/****************************************************************************
*
* WritePacket
*
***************************************************************************/
static int WritePacket(struct usb_device *cam, const u8 *packet)
{
if (packet == NULL) {
return -EINVAL;
}
return usb_control_msg(cpia->dev, usb_sndctrlpipe(cpia->dev, 0),
packet[1] + (packet[0] << 8),
USB_TYPE_VENDOR | USB_RECIP_DEVICE,
packet[2] + (packet[3] << 8),
packet[4] + (packet[5] << 8), NULL, 0, HZ);
}
/****************************************************************************
*
* ReadPacket
*
***************************************************************************/
static int ReadPacket(struct usb_device *cam, u8 *packet, u8 *buf, size_t size)
{
if (packet == NULL || size <= 0) {
return -EINVAL;
}
return usb_control_msg(cpia->dev, usb_rcvctrlpipe(cpia->dev, 0),
packet[1] + (packet[0] << 8),
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
packet[2] + (packet[3] << 8),
packet[4] + (packet[5] << 8), buf, size, HZ);
}
//
// Probing and initializing
//
static void * cpia_probe(struct usb_device *dev, unsigned int ifnum)
{
struct usb_interface_descriptor *interface;
struct usb_cpia *cpia;
/* We don't handle multi-config cameras */
if (dev->descriptor.bNumConfigurations != 1)
return NULL;
interface = &dev->actconfig->interface[ifnum].altsetting[0];
/* Is it a CPiA? */
if (dev->descriptor.idVendor != 0x0553)
return NULL;
if (dev->descriptor.idProduct != 0x0002)
return NULL;
/* Checking vendor/product should be enough, but what the hell */
if (interface->bInterfaceClass != 0xFF)
return NULL;
if (interface->bInterfaceSubClass != 0x00)
return NULL;
/* We found a CPiA */
printk(KERN_INFO "USB CPiA camera found\n");
if ((cpia = kmalloc(sizeof(*cpia), GFP_KERNEL)) == NULL) {
printk(KERN_ERR "couldn't kmalloc cpia struct\n");
return NULL;
}
memset(cpia, 0, sizeof(*cpia));
cpia->dev = dev;
cpia->iface = interface->bInterfaceNumber;
init_waitqueue(&cpia->wq_stream);
if (usb_set_interface(dev, iface, 0) < 0) {
printk(KERN_ERR "usb_set_interface error\n");
return NULL;
}
if(cpia_register_camera(&cpia_usb_ops, cpia)<0) {
LOG("failed to cpia_register_camera\n");
return NULL;
}
return cpia;
}
static void cpia_disconnect(struct usb_device *dev, void *ptr)
{
struct usb_cpia *cpia = (struct usb_cpia *) ptr;
// cpia_unregister_camera(cpia);
usb_driver_release_interface(&cpia_driver,
&cpia->dev->actconfig->interface[0]);
/* Free the memory */
kfree(cpia);
}
static struct usb_driver cpia_driver = {
"cpia",
cpia_probe,
cpia_disconnect,
{ NULL, NULL }
};
int usb_cpia_init(void)
{
return usb_register(&cpia_driver);
}
void usb_cpia_cleanup(void)
{
usb_deregister(&cpia_driver);
}
#ifdef MODULE
int init_module(void)
{
return usb_cpia_init();
}
void cleanup_module(void)
{
usb_cpia_cleanup();
}
#else /* !MODULE */
__initfunc(void cpia_usb_setup(char *str, int *ints))
{
}
#endif /* !MODULE */
--Multipart_Sun_Jan_16_22:18:55_2000-1--