/***************************************************************************
usbdrv.cpp - description
-------------------
begin : 五 9月 9 2005
copyright : (C) 2005 by root
email : root@localhost.localdomain
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#define __KERNEL__
#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <asm/uaccess.h rel='nofollow' onclick='return false;'>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/slab.h>
//#include <linux/devfs_fs_kernel.h>
#include <linux/version.h>
#include <linux/usb.h>
//#define DEBUG
//#ifdef DEBUG
#define db printk
//#define warn printk
// #define err printk
//#else
//#define db dbg
//#endif
#define USB_SN_VENDOR_ID 0x7890
#define USB_SN_PRODUCT_ID 0x0002
/* Get a minor range for your devices from the usb maintainer */
#define SCN_BASE_MNR 128
/* we can have up to this number of device plugged in at once */
#define MAX_DEVICES 16
#define IBUF_SIZE 16384*2
//32768
#define OBUF_SIZE 4096
#define CMD_READ_STATE 6
#define CMD_READ_DATA 8
#define IS_EP_BULK(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
#define IS_EP_INTR(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
#define USB_SN_MINOR(X) MINOR((X)->i_rdev) - SCN_BASE_MNR
#define SNUSB_IOCTL_READ_STATUS _IOWR('U', 0x26, void*)
#define SNUSB_IOCTL_USER_CODE _IOWR('U', 0x27, void*)
#define ENDPOINT_IN 0x2
#define ENDPOINT_OUT 0x0
#define ENDPOINT_INIR 0x1
//#define COMPANY "SinoData"
//#define DESCRIPTION "SinoData Usb Linux Driver by HP"
MODULE_AUTHOR("SinoData");
MODULE_DESCRIPTION("SinoData Usb Linux Driver by HP");
MODULE_LICENSE("GPL");
int ibuf_size=IBUF_SIZE;
struct scn_usb_data {
struct usb_device *scn_dev;
devfs_handle_t devfs; /* devfs device */
struct usb_interface* interface;
struct urb* write_urb;
unsigned int ifnum; /* Interface number of the USB device */
kdev_t scn_minor; /* sn minor - used in disconnect() */
unsigned char button; /* Front panel buffer */
char isopen; /* Not zero if the device is open */
char present; /* Not zero if device is present */
char *bulk_out_buffer;
char *bulk_in_buffer; /* transfer buffers */
char bulk_in_ep;
char bulk_out_ep;
char intr_ep; /* Endpoint assignments */
int bulk_in_size;
int bulk_out_size;
int open_count;
wait_queue_head_t rd_wait_q; /* read timeouts */
struct semaphore sem; /* lock to prevent concurrent reads or writes */
unsigned int rd_nak_timeout; /* Seconds to wait before read() timeout. */
};
/* the global usb devfs handle */
extern devfs_handle_t usb_devfs_handle;
static struct scn_usb_data *minor_table[MAX_DEVICES];
/* lock to protect the minor_table structure */
static DECLARE_MUTEX (minor_table_mutex);
static struct usb_device_id sn_table [] =
{
//{USB_DEVICE(0x7890,0x0002)},
{USB_DEVICE(USB_SN_VENDOR_ID, USB_SN_PRODUCT_ID)},
{}
};
MODULE_DEVICE_TABLE (usb, sn_table);
////////////////////////-----------------------------------------------------------------
static void usb_show_endpoint(struct usb_endpoint_descriptor *endpoint)
/* [<][>][^][v][top][bottom][index][help] */
{
usb_show_endpoint_descriptor(endpoint);
}
static void usb_show_interface(struct usb_interface_descriptor *altsetting)
/* [<][>][^][v][top][bottom][index][help] */
{
int i;
usb_show_interface_descriptor(altsetting);
for (i = 0; i < altsetting->bNumEndpoints; i++)
usb_show_endpoint(altsetting->endpoint + i);
}
static void usb_show_config(struct usb_config_descriptor *config)
/* [<][>][^][v][top][bottom][index][help] */
{
int i, j;
struct usb_interface *ifp;
usb_show_config_descriptor(config);
for (i = 0; i < config->bNumInterfaces; i++) {
ifp = config->interface + i;
if (!ifp)
break;
printk("\n Interface: %d\n", i);
for (j = 0; j < ifp->num_altsetting; j++)
usb_show_interface(ifp->altsetting + j);
}
}
void usb_show_device(struct usb_device *dev)
/* [<][>][^][v][top][bottom][index][help] */
{
int i;
usb_show_device_descriptor(&dev->descriptor);
for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
usb_show_config(dev->config + i);
}
/*
* Parse and show the different USB descriptors.
*/
void usb_show_device_descriptor(struct usb_device_descriptor *desc)
/* [<][>][^][v][top][bottom][index][help] */
{
if (!desc)
{
db("Invalid USB device descriptor (NULL POINTER)\n");
return;
}
db(" Length = %2d%s\n", desc->bLength,
desc->bLength == USB_DT_DEVICE_SIZE ? "" : " (!!!)");
db(" DescriptorType = %02x\n", desc->bDescriptorType);
db(" USB version = %x.%02x\n",
desc->bcdUSB >> 8, desc->bcdUSB & 0xff);
db(" Vendor:Product = %04x:%04x\n",
desc->idVendor, desc->idProduct);
db(" MaxPacketSize0 = %d\n", desc->bMaxPacketSize0);
db(" NumConfigurations = %d\n", desc->bNumConfigurations);
db(" Device version = %x.%02x\n",
desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
db(" Device Class:SubClass:Protocol = %02x:%02x:%02x\n",
desc->bDeviceClass, desc->bDeviceSubClass, desc->bDeviceProtocol);
switch (desc->bDeviceClass) {
case 0:
db(" Per-interface classes\n");
break;
case USB_CLASS_AUDIO:
db(" Audio device class\n");
break;
case USB_CLASS_COMM:
db(" Communications class\n");
break;
case USB_CLASS_HID:
db(" Human Interface Devices class\n");
break;
case USB_CLASS_PRINTER:
db(" Printer device class\n");
break;
case USB_CLASS_MASS_STORAGE:
db(" Mass Storage device class\n");
break;
case USB_CLASS_HUB:
db(" Hub device class\n");
break;
case USB_CLASS_VENDOR_SPEC:
db(" Vendor class\n");
break;
default:
db(" Unknown class\n");
}
}
void usb_show_config_descriptor(struct usb_config_descriptor *desc)
/* [<][>][^][v][top][bottom][index][help] */
{
db("Configuration:\n");
db(" bLength = %4d%s\n", desc->bLength,
desc->bLength == USB_DT_CONFIG_SIZE ? "" : " (!!!)");
db(" bDescriptorType = %02x\n", desc->bDescriptorType);
db(" wTotalLength = %04x\n", desc->wTotalLength);
db(" bNumInter