Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
This commit is contained in:
Linus Torvalds
2005-04-16 15:20:36 -07:00
當前提交 1da177e4c3
共有 17291 個文件被更改,包括 6718755 次插入0 次删除

152
drivers/usb/misc/Kconfig Normal file
查看文件

@@ -0,0 +1,152 @@
#
# USB Miscellaneous driver configuration
#
comment "USB Miscellaneous drivers"
depends on USB
config USB_EMI62
tristate "EMI 6|2m USB Audio interface support"
depends on USB
---help---
This driver loads firmware to Emagic EMI 6|2m low latency USB
Audio and Midi interface.
After firmware load the device is handled with standard linux
USB Audio driver.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called audio. If you want to compile it as a
module, say M here and read <file:Documentation/kbuild/modules.txt>.
config USB_EMI26
tristate "EMI 2|6 USB Audio interface support"
depends on USB
---help---
This driver loads firmware to Emagic EMI 2|6 low latency USB
Audio interface.
After firmware load the device is handled with standard linux
USB Audio driver.
To compile this driver as a module, choose M here: the
module will be called emi26.
config USB_AUERSWALD
tristate "USB Auerswald ISDN support (EXPERIMENTAL)"
depends on USB && EXPERIMENTAL
help
Say Y here if you want to connect an Auerswald USB ISDN Device
to your computer's USB port.
To compile this driver as a module, choose M here: the
module will be called auerswald.
config USB_RIO500
tristate "USB Diamond Rio500 support (EXPERIMENTAL)"
depends on USB && EXPERIMENTAL
help
Say Y here if you want to connect a USB Rio500 mp3 player to your
computer's USB port. Please read <file:Documentation/usb/rio.txt>
for more information.
To compile this driver as a module, choose M here: the
module will be called rio500.
config USB_LEGOTOWER
tristate "USB Lego Infrared Tower support (EXPERIMENTAL)"
depends on USB && EXPERIMENTAL
help
Say Y here if you want to connect a USB Lego Infrared Tower to your
computer's USB port.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called legousbtower. If you want to compile it as
a module, say M here and read
<file:Documentation/kbuild/modules.txt>.
config USB_LCD
tristate "USB LCD driver support"
depends on USB
help
Say Y here if you want to connect an USBLCD to your computer's
USB port. The USBLCD is a small USB interface board for
alphanumeric LCD modules. See <http://www.usblcd.de/> for more
information.
To compile this driver as a module, choose M here: the
module will be called usblcd.
config USB_LED
tristate "USB LED driver support"
depends on USB
help
Say Y here if you want to connect an USBLED device to your
computer's USB port.
To compile this driver as a module, choose M here: the
module will be called usbled.
config USB_CYTHERM
tristate "Cypress USB thermometer driver support"
depends on USB
help
Say Y here if you want to connect a Cypress USB thermometer
device to your computer's USB port. This device is also known
as the Cypress USB Starter kit or demo board. The Elektor
magazine published a modified version of this device in issue
#291.
To compile this driver as a module, choose M here: the
module will be called cytherm.
config USB_PHIDGETKIT
tristate "USB PhidgetKit support"
depends on USB
help
Say Y here if you want to connect a PhidgetKit USB device from
Phidgets Inc.
To compile this driver as a module, choose M here: the
module will be called phidgetkit.
config USB_PHIDGETSERVO
tristate "USB PhidgetServo support"
depends on USB
help
Say Y here if you want to connect an 1 or 4 Motor PhidgetServo
servo controller version 2.0 or 3.0.
Phidgets Inc. has a web page at <http://www.phidgets.com/>.
To compile this driver as a module, choose M here: the
module will be called phidgetservo.
config USB_IDMOUSE
tristate "Siemens ID USB Mouse Fingerprint sensor support"
depends on USB
help
Say Y here if you want to use the fingerprint sensor on
the Siemens ID Mouse. There is also a Siemens ID Mouse
_Professional_, which has not been tested with this driver,
but uses the same sensor and may therefore work.
This driver creates an entry "/dev/idmouseX" or "/dev/usb/idmouseX",
which can be used by, e.g.,"cat /dev/idmouse0 > fingerprint.pnm".
See also <http://www.fs.tum.de/~echtler/idmouse/>.
source "drivers/usb/misc/sisusbvga/Kconfig"
config USB_TEST
tristate "USB testing driver (DEVELOPMENT)"
depends on USB && USB_DEVICEFS && EXPERIMENTAL
help
This driver is for testing host controller software. It is used
with specialized device firmware for regression and stress testing,
to help prevent problems from cropping up with "real" drivers.
See <http://www.linux-usb.org/usbtest/> for more information,
including sample test device firmware and "how to use it".

20
drivers/usb/misc/Makefile Normal file
查看文件

@@ -0,0 +1,20 @@
#
# Makefile for the rest of the USB drivers
# (the ones that don't fit into any other categories)
#
obj-$(CONFIG_USB_AUERSWALD) += auerswald.o
obj-$(CONFIG_USB_CYTHERM) += cytherm.o
obj-$(CONFIG_USB_EMI26) += emi26.o
obj-$(CONFIG_USB_EMI62) += emi62.o
obj-$(CONFIG_USB_IDMOUSE) += idmouse.o
obj-$(CONFIG_USB_LCD) += usblcd.o
obj-$(CONFIG_USB_LED) += usbled.o
obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o
obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o
obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o
obj-$(CONFIG_USB_RIO500) += rio500.o
obj-$(CONFIG_USB_TEST) += usbtest.o
obj-$(CONFIG_USB_USS720) += uss720.o
obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/

2163
drivers/usb/misc/auerswald.c Normal file

文件差異過大導致無法顯示 Load Diff

430
drivers/usb/misc/cytherm.c Normal file
查看文件

@@ -0,0 +1,430 @@
/* -*- linux-c -*-
* Cypress USB Thermometer driver
*
* Copyright (c) 2004 Erik Rigtorp <erkki@linux.nu> <erik@rigtorp.com>
*
* This driver works with Elektor magazine USB Interface as published in
* issue #291. It should also work with the original starter kit/demo board
* from Cypress.
*
* 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, version 2.
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/usb.h>
#define DRIVER_VERSION "v1.0"
#define DRIVER_AUTHOR "Erik Rigtorp"
#define DRIVER_DESC "Cypress USB Thermometer driver"
#define USB_SKEL_VENDOR_ID 0x04b4
#define USB_SKEL_PRODUCT_ID 0x0002
static struct usb_device_id id_table [] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
{ }
};
MODULE_DEVICE_TABLE (usb, id_table);
/* Structure to hold all of our device specific stuff */
struct usb_cytherm {
struct usb_device *udev; /* save off the usb device pointer */
struct usb_interface *interface; /* the interface for this device */
int brightness;
};
/* local function prototypes */
static int cytherm_probe(struct usb_interface *interface,
const struct usb_device_id *id);
static void cytherm_disconnect(struct usb_interface *interface);
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver cytherm_driver = {
.owner = THIS_MODULE,
.name = "cytherm",
.probe = cytherm_probe,
.disconnect = cytherm_disconnect,
.id_table = id_table,
};
/* Vendor requests */
/* They all operate on one byte at a time */
#define PING 0x00
#define READ_ROM 0x01 /* Reads form ROM, value = address */
#define READ_RAM 0x02 /* Reads form RAM, value = address */
#define WRITE_RAM 0x03 /* Write to RAM, value = address, index = data */
#define READ_PORT 0x04 /* Reads from port, value = address */
#define WRITE_PORT 0x05 /* Write to port, value = address, index = data */
/* Send a vendor command to device */
static int vendor_command(struct usb_device *dev, unsigned char request,
unsigned char value, unsigned char index,
void *buf, int size)
{
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
request,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
value,
index, buf, size,
USB_CTRL_GET_TIMEOUT);
}
#define BRIGHTNESS 0x2c /* RAM location for brightness value */
#define BRIGHTNESS_SEM 0x2b /* RAM location for brightness semaphore */
static ssize_t show_brightness(struct device *dev, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_cytherm *cytherm = usb_get_intfdata(intf);
return sprintf(buf, "%i", cytherm->brightness);
}
static ssize_t set_brightness(struct device *dev, const char *buf,
size_t count)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_cytherm *cytherm = usb_get_intfdata(intf);
unsigned char *buffer;
int retval;
buffer = kmalloc(8, GFP_KERNEL);
if (!buffer) {
dev_err(&cytherm->udev->dev, "out of memory\n");
return 0;
}
cytherm->brightness = simple_strtoul(buf, NULL, 10);
if (cytherm->brightness > 0xFF)
cytherm->brightness = 0xFF;
else if (cytherm->brightness < 0)
cytherm->brightness = 0;
/* Set brightness */
retval = vendor_command(cytherm->udev, WRITE_RAM, BRIGHTNESS,
cytherm->brightness, buffer, 8);
if (retval)
dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
/* Inform <20>C that we have changed the brightness setting */
retval = vendor_command(cytherm->udev, WRITE_RAM, BRIGHTNESS_SEM,
0x01, buffer, 8);
if (retval)
dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
kfree(buffer);
return count;
}
static DEVICE_ATTR(brightness, S_IRUGO | S_IWUSR | S_IWGRP,
show_brightness, set_brightness);
#define TEMP 0x33 /* RAM location for temperature */
#define SIGN 0x34 /* RAM location for temperature sign */
static ssize_t show_temp(struct device *dev, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_cytherm *cytherm = usb_get_intfdata(intf);
int retval;
unsigned char *buffer;
int temp, sign;
buffer = kmalloc(8, GFP_KERNEL);
if (!buffer) {
dev_err(&cytherm->udev->dev, "out of memory\n");
return 0;
}
/* read temperature */
retval = vendor_command(cytherm->udev, READ_RAM, TEMP, 0, buffer, 8);
if (retval)
dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
temp = buffer[1];
/* read sign */
retval = vendor_command(cytherm->udev, READ_RAM, SIGN, 0, buffer, 8);
if (retval)
dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
sign = buffer[1];
kfree(buffer);
return sprintf(buf, "%c%i.%i", sign ? '-' : '+', temp >> 1,
5*(temp - ((temp >> 1) << 1)));
}
static ssize_t set_temp(struct device *dev, const char *buf, size_t count)
{
return count;
}
static DEVICE_ATTR(temp, S_IRUGO, show_temp, set_temp);
#define BUTTON 0x7a
static ssize_t show_button(struct device *dev, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_cytherm *cytherm = usb_get_intfdata(intf);
int retval;
unsigned char *buffer;
buffer = kmalloc(8, GFP_KERNEL);
if (!buffer) {
dev_err(&cytherm->udev->dev, "out of memory\n");
return 0;
}
/* check button */
retval = vendor_command(cytherm->udev, READ_RAM, BUTTON, 0, buffer, 8);
if (retval)
dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
retval = buffer[1];
kfree(buffer);
if (retval)
return sprintf(buf, "1");
else
return sprintf(buf, "0");
}
static ssize_t set_button(struct device *dev, const char *buf, size_t count)
{
return count;
}
static DEVICE_ATTR(button, S_IRUGO, show_button, set_button);
static ssize_t show_port0(struct device *dev, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_cytherm *cytherm = usb_get_intfdata(intf);
int retval;
unsigned char *buffer;
buffer = kmalloc(8, GFP_KERNEL);
if (!buffer) {
dev_err(&cytherm->udev->dev, "out of memory\n");
return 0;
}
retval = vendor_command(cytherm->udev, READ_PORT, 0, 0, buffer, 8);
if (retval)
dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
retval = buffer[1];
kfree(buffer);
return sprintf(buf, "%d", retval);
}
static ssize_t set_port0(struct device *dev, const char *buf, size_t count)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_cytherm *cytherm = usb_get_intfdata(intf);
unsigned char *buffer;
int retval;
int tmp;
buffer = kmalloc(8, GFP_KERNEL);
if (!buffer) {
dev_err(&cytherm->udev->dev, "out of memory\n");
return 0;
}
tmp = simple_strtoul(buf, NULL, 10);
if (tmp > 0xFF)
tmp = 0xFF;
else if (tmp < 0)
tmp = 0;
retval = vendor_command(cytherm->udev, WRITE_PORT, 0,
tmp, buffer, 8);
if (retval)
dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
kfree(buffer);
return count;
}
static DEVICE_ATTR(port0, S_IRUGO | S_IWUSR | S_IWGRP, show_port0, set_port0);
static ssize_t show_port1(struct device *dev, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_cytherm *cytherm = usb_get_intfdata(intf);
int retval;
unsigned char *buffer;
buffer = kmalloc(8, GFP_KERNEL);
if (!buffer) {
dev_err(&cytherm->udev->dev, "out of memory\n");
return 0;
}
retval = vendor_command(cytherm->udev, READ_PORT, 1, 0, buffer, 8);
if (retval)
dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
retval = buffer[1];
kfree(buffer);
return sprintf(buf, "%d", retval);
}
static ssize_t set_port1(struct device *dev, const char *buf, size_t count)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_cytherm *cytherm = usb_get_intfdata(intf);
unsigned char *buffer;
int retval;
int tmp;
buffer = kmalloc(8, GFP_KERNEL);
if (!buffer) {
dev_err(&cytherm->udev->dev, "out of memory\n");
return 0;
}
tmp = simple_strtoul(buf, NULL, 10);
if (tmp > 0xFF)
tmp = 0xFF;
else if (tmp < 0)
tmp = 0;
retval = vendor_command(cytherm->udev, WRITE_PORT, 1,
tmp, buffer, 8);
if (retval)
dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
kfree(buffer);
return count;
}
static DEVICE_ATTR(port1, S_IRUGO | S_IWUSR | S_IWGRP, show_port1, set_port1);
static int cytherm_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(interface);
struct usb_cytherm *dev = NULL;
int retval = -ENOMEM;
dev = kmalloc (sizeof(struct usb_cytherm), GFP_KERNEL);
if (dev == NULL) {
dev_err (&interface->dev, "Out of memory\n");
goto error;
}
memset (dev, 0x00, sizeof (*dev));
dev->udev = usb_get_dev(udev);
usb_set_intfdata (interface, dev);
dev->brightness = 0xFF;
device_create_file(&interface->dev, &dev_attr_brightness);
device_create_file(&interface->dev, &dev_attr_temp);
device_create_file(&interface->dev, &dev_attr_button);
device_create_file(&interface->dev, &dev_attr_port0);
device_create_file(&interface->dev, &dev_attr_port1);
dev_info (&interface->dev,
"Cypress thermometer device now attached\n");
return 0;
error:
kfree(dev);
return retval;
}
static void cytherm_disconnect(struct usb_interface *interface)
{
struct usb_cytherm *dev;
dev = usb_get_intfdata (interface);
usb_set_intfdata (interface, NULL);
device_remove_file(&interface->dev, &dev_attr_brightness);
device_remove_file(&interface->dev, &dev_attr_temp);
device_remove_file(&interface->dev, &dev_attr_button);
device_remove_file(&interface->dev, &dev_attr_port0);
device_remove_file(&interface->dev, &dev_attr_port1);
usb_put_dev(dev->udev);
kfree(dev);
dev_info(&interface->dev, "Cypress thermometer now disconnected\n");
}
static int __init usb_cytherm_init(void)
{
int result;
result = usb_register(&cytherm_driver);
if (result)
{
err("usb_register failed. Error number %d", result);
return result;
}
info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
}
static void __exit usb_cytherm_exit(void)
{
usb_deregister(&cytherm_driver);
}
module_init (usb_cytherm_init);
module_exit (usb_cytherm_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

255
drivers/usb/misc/emi26.c Normal file
查看文件

@@ -0,0 +1,255 @@
/*
* Emagic EMI 2|6 usb audio interface firmware loader.
* Copyright (C) 2002
* Tapio Laxstr<74>m (tapio.laxstrom@iptime.fi)
*
* 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, version 2.
*
* emi26.c,v 1.13 2002/03/08 13:10:26 tapio Exp
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb.h>
#define MAX_INTEL_HEX_RECORD_LENGTH 16
typedef struct _INTEL_HEX_RECORD
{
__u32 length;
__u32 address;
__u32 type;
__u8 data[MAX_INTEL_HEX_RECORD_LENGTH];
} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD;
/* include firmware (variables) */
#include "emi26_fw.h"
#define EMI26_VENDOR_ID 0x086a /* Emagic Soft-und Hardware GmBH */
#define EMI26_PRODUCT_ID 0x0100 /* EMI 2|6 without firmware */
#define EMI26B_PRODUCT_ID 0x0102 /* EMI 2|6 without firmware */
#define ANCHOR_LOAD_INTERNAL 0xA0 /* Vendor specific request code for Anchor Upload/Download (This one is implemented in the core) */
#define ANCHOR_LOAD_EXTERNAL 0xA3 /* This command is not implemented in the core. Requires firmware */
#define ANCHOR_LOAD_FPGA 0xA5 /* This command is not implemented in the core. Requires firmware. Emagic extension */
#define MAX_INTERNAL_ADDRESS 0x1B3F /* This is the highest internal RAM address for the AN2131Q */
#define CPUCS_REG 0x7F92 /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
#define INTERNAL_RAM(address) (address <= MAX_INTERNAL_ADDRESS)
static int emi26_writememory( struct usb_device *dev, int address, unsigned char *data, int length, __u8 bRequest);
static int emi26_set_reset(struct usb_device *dev, unsigned char reset_bit);
static int emi26_load_firmware (struct usb_device *dev);
static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id);
static void emi26_disconnect(struct usb_interface *intf);
static int __init emi26_init (void);
static void __exit emi26_exit (void);
/* thanks to drivers/usb/serial/keyspan_pda.c code */
static int emi26_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request)
{
int result;
unsigned char *buffer = kmalloc (length, GFP_KERNEL);
if (!buffer) {
err("emi26: kmalloc(%d) failed.", length);
return -ENOMEM;
}
memcpy (buffer, data, length);
/* Note: usb_control_msg returns negative value on error or length of the
* data that was written! */
result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
kfree (buffer);
return result;
}
/* thanks to drivers/usb/serial/keyspan_pda.c code */
static int emi26_set_reset (struct usb_device *dev, unsigned char reset_bit)
{
int response;
info("%s - %d", __FUNCTION__, reset_bit);
/* printk(KERN_DEBUG "%s - %d", __FUNCTION__, reset_bit); */
response = emi26_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0);
if (response < 0) {
err("emi26: set_reset (%d) failed", reset_bit);
}
return response;
}
#define FW_LOAD_SIZE 1023
static int emi26_load_firmware (struct usb_device *dev)
{
int err;
int i;
int pos = 0; /* Position in hex record */
__u32 addr; /* Address to write */
__u8 *buf;
buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL);
if (!buf) {
err( "%s - error loading firmware: error = %d", __FUNCTION__, -ENOMEM);
err = -ENOMEM;
goto wraperr;
}
/* Assert reset (stop the CPU in the EMI) */
err = emi26_set_reset(dev,1);
if (err < 0) {
err( "%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
/* 1. We need to put the loader for the FPGA into the EZ-USB */
for (i=0; g_Loader[i].type == 0; i++) {
err = emi26_writememory(dev, g_Loader[i].address, g_Loader[i].data, g_Loader[i].length, ANCHOR_LOAD_INTERNAL);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
}
/* De-assert reset (let the CPU run) */
err = emi26_set_reset(dev,0);
/* 2. We upload the FPGA firmware into the EMI
* Note: collect up to 1023 (yes!) bytes and send them with
* a single request. This is _much_ faster! */
do {
i = 0;
addr = g_bitstream[pos].address;
/* intel hex records are terminated with type 0 element */
while ((g_bitstream[pos].type == 0) && (i + g_bitstream[pos].length < FW_LOAD_SIZE)) {
memcpy(buf + i, g_bitstream[pos].data, g_bitstream[pos].length);
i += g_bitstream[pos].length;
pos++;
}
err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
} while (i > 0);
/* Assert reset (stop the CPU in the EMI) */
err = emi26_set_reset(dev,1);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
/* 3. We need to put the loader for the firmware into the EZ-USB (again...) */
for (i=0; g_Loader[i].type == 0; i++) {
err = emi26_writememory(dev, g_Loader[i].address, g_Loader[i].data, g_Loader[i].length, ANCHOR_LOAD_INTERNAL);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
}
/* De-assert reset (let the CPU run) */
err = emi26_set_reset(dev,0);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
/* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */
for (i=0; g_Firmware[i].type == 0; i++) {
if (!INTERNAL_RAM(g_Firmware[i].address)) {
err = emi26_writememory(dev, g_Firmware[i].address, g_Firmware[i].data, g_Firmware[i].length, ANCHOR_LOAD_EXTERNAL);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
}
}
/* Assert reset (stop the CPU in the EMI) */
err = emi26_set_reset(dev,1);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
for (i=0; g_Firmware[i].type == 0; i++) {
if (INTERNAL_RAM(g_Firmware[i].address)) {
err = emi26_writememory(dev, g_Firmware[i].address, g_Firmware[i].data, g_Firmware[i].length, ANCHOR_LOAD_INTERNAL);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
}
}
/* De-assert reset (let the CPU run) */
err = emi26_set_reset(dev,0);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
/* return 1 to fail the driver inialization
* and give real driver change to load */
err = 1;
wraperr:
kfree(buf);
return err;
}
static struct usb_device_id id_table [] = {
{ USB_DEVICE(EMI26_VENDOR_ID, EMI26_PRODUCT_ID) },
{ USB_DEVICE(EMI26_VENDOR_ID, EMI26B_PRODUCT_ID) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, id_table);
static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
info("%s start", __FUNCTION__);
emi26_load_firmware(dev);
/* do not return the driver context, let real audio driver do that */
return -EIO;
}
static void emi26_disconnect(struct usb_interface *intf)
{
}
static struct usb_driver emi26_driver = {
.owner = THIS_MODULE,
.name = "emi26 - firmware loader",
.probe = emi26_probe,
.disconnect = emi26_disconnect,
.id_table = id_table,
};
static int __init emi26_init (void)
{
return usb_register(&emi26_driver);
}
static void __exit emi26_exit (void)
{
usb_deregister (&emi26_driver);
}
module_init(emi26_init);
module_exit(emi26_exit);
MODULE_AUTHOR("tapio laxstr<74>m");
MODULE_DESCRIPTION("Emagic EMI 2|6 firmware loader.");
MODULE_LICENSE("GPL");
/* vi:ai:syntax=c:sw=8:ts=8:tw=80
*/

5779
drivers/usb/misc/emi26_fw.h Normal file

文件差異過大導致無法顯示 Load Diff

298
drivers/usb/misc/emi62.c Normal file
查看文件

@@ -0,0 +1,298 @@
/*
* Emagic EMI 2|6 usb audio interface firmware loader.
* Copyright (C) 2002
* Tapio Laxstr<74>m (tapio.laxstrom@iptime.fi)
*
* 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, version 2.
*
* $Id: emi62.c,v 1.15 2002/04/23 06:13:59 tapio Exp $
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/usb.h>
#define MAX_INTEL_HEX_RECORD_LENGTH 16
typedef struct _INTEL_HEX_RECORD
{
__u32 length;
__u32 address;
__u32 type;
__u8 data[MAX_INTEL_HEX_RECORD_LENGTH];
} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD;
/* include firmware (variables)*/
/* FIXME: This is quick and dirty solution! */
#define SPDIF /* if you want SPDIF comment next line */
//#undef SPDIF /* if you want MIDI uncomment this line */
#ifdef SPDIF
# include "emi62_fw_s.h" /* spdif fw */
#else
# include "emi62_fw_m.h" /* midi fw */
#endif
#define EMI62_VENDOR_ID 0x086a /* Emagic Soft-und Hardware GmBH */
#define EMI62_PRODUCT_ID 0x0110 /* EMI 6|2m without firmware */
#define ANCHOR_LOAD_INTERNAL 0xA0 /* Vendor specific request code for Anchor Upload/Download (This one is implemented in the core) */
#define ANCHOR_LOAD_EXTERNAL 0xA3 /* This command is not implemented in the core. Requires firmware */
#define ANCHOR_LOAD_FPGA 0xA5 /* This command is not implemented in the core. Requires firmware. Emagic extension */
#define MAX_INTERNAL_ADDRESS 0x1B3F /* This is the highest internal RAM address for the AN2131Q */
#define CPUCS_REG 0x7F92 /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
#define INTERNAL_RAM(address) (address <= MAX_INTERNAL_ADDRESS)
static int emi62_writememory( struct usb_device *dev, int address, unsigned char *data, int length, __u8 bRequest);
static int emi62_set_reset(struct usb_device *dev, unsigned char reset_bit);
static int emi62_load_firmware (struct usb_device *dev);
static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id);
static void emi62_disconnect(struct usb_interface *intf);
static int __init emi62_init (void);
static void __exit emi62_exit (void);
/* thanks to drivers/usb/serial/keyspan_pda.c code */
static int emi62_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request)
{
int result;
unsigned char *buffer = kmalloc (length, GFP_KERNEL);
if (!buffer) {
err("emi62: kmalloc(%d) failed.", length);
return -ENOMEM;
}
memcpy (buffer, data, length);
/* Note: usb_control_msg returns negative value on error or length of the
* data that was written! */
result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
kfree (buffer);
return result;
}
/* thanks to drivers/usb/serial/keyspan_pda.c code */
static int emi62_set_reset (struct usb_device *dev, unsigned char reset_bit)
{
int response;
info("%s - %d", __FUNCTION__, reset_bit);
response = emi62_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0);
if (response < 0) {
err("emi62: set_reset (%d) failed", reset_bit);
}
return response;
}
#define FW_LOAD_SIZE 1023
static int emi62_load_firmware (struct usb_device *dev)
{
int err;
int i;
int pos = 0; /* Position in hex record */
__u32 addr; /* Address to write */
__u8 *buf;
dev_dbg(&dev->dev, "load_firmware\n");
buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL);
if (!buf) {
err( "%s - error loading firmware: error = %d", __FUNCTION__, -ENOMEM);
err = -ENOMEM;
goto wraperr;
}
/* Assert reset (stop the CPU in the EMI) */
err = emi62_set_reset(dev,1);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
/* 1. We need to put the loader for the FPGA into the EZ-USB */
for (i=0; g_emi62_loader[i].type == 0; i++) {
err = emi62_writememory(dev, g_emi62_loader[i].address, g_emi62_loader[i].data, g_emi62_loader[i].length, ANCHOR_LOAD_INTERNAL);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
}
/* De-assert reset (let the CPU run) */
err = emi62_set_reset(dev,0);
/* 2. We upload the FPGA firmware into the EMI
* Note: collect up to 1023 (yes!) bytes and send them with
* a single request. This is _much_ faster! */
do {
i = 0;
addr = g_emi62bs[pos].address;
/* intel hex records are terminated with type 0 element */
while ((g_emi62bs[pos].type == 0) && (i + g_emi62bs[pos].length < FW_LOAD_SIZE)) {
memcpy(buf + i, g_emi62bs[pos].data, g_emi62bs[pos].length);
i += g_emi62bs[pos].length;
pos++;
}
err = emi62_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
} while (i > 0);
/* Assert reset (stop the CPU in the EMI) */
err = emi62_set_reset(dev,1);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
/* 3. We need to put the loader for the firmware into the EZ-USB (again...) */
for (i=0; g_emi62_loader[i].type == 0; i++) {
err = emi62_writememory(dev, g_emi62_loader[i].address, g_emi62_loader[i].data, g_emi62_loader[i].length, ANCHOR_LOAD_INTERNAL);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
}
/* De-assert reset (let the CPU run) */
err = emi62_set_reset(dev,0);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
/* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */
/* FIXME: quick and dirty ifdefs */
#ifdef SPDIF
for (i=0; g_HexSpdifFw62[i].type == 0; i++) {
if (!INTERNAL_RAM(g_HexSpdifFw62[i].address)) {
err = emi62_writememory(dev, g_HexSpdifFw62[i].address, g_HexSpdifFw62[i].data, g_HexSpdifFw62[i].length, ANCHOR_LOAD_EXTERNAL);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
}
}
#else /* MIDI */
for (i=0; g_HexMidiFw62[i].type == 0; i++) {
if (!INTERNAL_RAM(g_HexMidiFw62[i].address)) {
err = emi62_writememory(dev, g_HexMidiFw62[i].address, g_HexMidiFw62[i].data, g_HexMidiFw62[i].length, ANCHOR_LOAD_EXTERNAL);
if (err < 0) {
err("%s - error loading firmware: error = %d\n", __FUNCTION__, err);
goto wraperr;
return err;
}
}
}
#endif
/* Assert reset (stop the CPU in the EMI) */
err = emi62_set_reset(dev,1);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
/* FIXME: quick and dirty ifdefs */
#ifdef SPDIF
for (i=0; g_HexSpdifFw62[i].type == 0; i++) {
if (INTERNAL_RAM(g_HexSpdifFw62[i].address)) {
err = emi62_writememory(dev, g_HexSpdifFw62[i].address, g_HexSpdifFw62[i].data, g_HexSpdifFw62[i].length, ANCHOR_LOAD_INTERNAL);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
}
}
#else /* MIDI */
for (i=0; g_HexMidiFw62[i].type == 0; i++) {
if (INTERNAL_RAM(g_HexMidiFw62[i].address)) {
err = emi62_writememory(dev, g_HexMidiFw62[i].address, g_HexMidiFw62[i].data, g_HexMidiFw62[i].length, ANCHOR_LOAD_INTERNAL);
if (err < 0) {
err("%s - error loading firmware: error = %d\n", __FUNCTION__, err);
goto wraperr;
}
}
}
#endif
/* De-assert reset (let the CPU run) */
err = emi62_set_reset(dev,0);
if (err < 0) {
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
kfree(buf);
/* return 1 to fail the driver inialization
* and give real driver change to load */
return 1;
wraperr:
kfree(buf);
dev_err(&dev->dev, "Error\n");
return err;
}
static __devinitdata struct usb_device_id id_table [] = {
{ USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, id_table);
static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
dev_dbg(&intf->dev, "emi62_probe\n");
info("%s start", __FUNCTION__);
emi62_load_firmware(dev);
/* do not return the driver context, let real audio driver do that */
return -EIO;
}
static void emi62_disconnect(struct usb_interface *intf)
{
}
static struct usb_driver emi62_driver = {
.owner = THIS_MODULE,
.name = "emi62 - firmware loader",
.probe = emi62_probe,
.disconnect = emi62_disconnect,
.id_table = id_table,
};
static int __init emi62_init (void)
{
int retval;
retval = usb_register (&emi62_driver);
if (retval)
printk(KERN_ERR "adi-emi: registration failed\n");
return retval;
}
static void __exit emi62_exit (void)
{
usb_deregister (&emi62_driver);
}
module_init(emi62_init);
module_exit(emi62_exit);
MODULE_AUTHOR("tapio laxstr<74>m");
MODULE_DESCRIPTION("Emagic EMI 6|2m firmware loader.");
MODULE_LICENSE("GPL");
/* vi:ai:syntax=c:sw=8:ts=8:tw=80
*/

文件差異過大導致無法顯示 Load Diff

文件差異過大導致無法顯示 Load Diff

443
drivers/usb/misc/idmouse.c Normal file
查看文件

@@ -0,0 +1,443 @@
/* Siemens ID Mouse driver v0.5
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.
Copyright (C) 2004-5 by Florian 'Floe' Echtler <echtler@fs.tum.de>
and Andreas 'ad' Deresch <aderesch@fs.tum.de>
Derived from the USB Skeleton driver 1.1,
Copyright (C) 2003 Greg Kroah-Hartman (greg@kroah.com)
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
#define WIDTH 225
#define HEIGHT 288
#define HEADER "P5 225 288 255 "
#define IMGSIZE ((WIDTH * HEIGHT) + sizeof(HEADER)-1)
/* Version Information */
#define DRIVER_VERSION "0.5"
#define DRIVER_SHORT "idmouse"
#define DRIVER_AUTHOR "Florian 'Floe' Echtler <echtler@fs.tum.de>"
#define DRIVER_DESC "Siemens ID Mouse FingerTIP Sensor Driver"
/* Siemens ID Mouse */
#define USB_IDMOUSE_VENDOR_ID 0x0681
#define USB_IDMOUSE_PRODUCT_ID 0x0005
/* we still need a minor number */
#define USB_IDMOUSE_MINOR_BASE 132
static struct usb_device_id idmouse_table[] = {
{USB_DEVICE(USB_IDMOUSE_VENDOR_ID, USB_IDMOUSE_PRODUCT_ID)},
{} /* null entry at the end */
};
MODULE_DEVICE_TABLE(usb, idmouse_table);
/* structure to hold all of our device specific stuff */
struct usb_idmouse {
struct usb_device *udev; /* save off the usb device pointer */
struct usb_interface *interface; /* the interface for this device */
unsigned char *bulk_in_buffer; /* the buffer to receive data */
size_t bulk_in_size; /* the size of the receive buffer */
__u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
int open; /* if the port is open or not */
int present; /* if the device is not disconnected */
struct semaphore sem; /* locks this structure */
};
/* local function prototypes */
static ssize_t idmouse_read(struct file *file, char __user *buffer,
size_t count, loff_t * ppos);
static int idmouse_open(struct inode *inode, struct file *file);
static int idmouse_release(struct inode *inode, struct file *file);
static int idmouse_probe(struct usb_interface *interface,
const struct usb_device_id *id);
static void idmouse_disconnect(struct usb_interface *interface);
/* file operation pointers */
static struct file_operations idmouse_fops = {
.owner = THIS_MODULE,
.read = idmouse_read,
.open = idmouse_open,
.release = idmouse_release,
};
/* class driver information for devfs */
static struct usb_class_driver idmouse_class = {
.name = "usb/idmouse%d",
.fops = &idmouse_fops,
.mode = S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, /* filemode (char, 444) */
.minor_base = USB_IDMOUSE_MINOR_BASE,
};
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver idmouse_driver = {
.owner = THIS_MODULE,
.name = DRIVER_SHORT,
.probe = idmouse_probe,
.disconnect = idmouse_disconnect,
.id_table = idmouse_table,
};
// prevent races between open() and disconnect()
static DECLARE_MUTEX(disconnect_sem);
static int idmouse_create_image(struct usb_idmouse *dev)
{
int bytes_read = 0;
int bulk_read = 0;
int result = 0;
if (dev->bulk_in_size < sizeof(HEADER))
return -ENOMEM;
memcpy(dev->bulk_in_buffer,HEADER,sizeof(HEADER)-1);
bytes_read += sizeof(HEADER)-1;
/* Dump the setup packets. Yes, they are uncommented, simply
because they were sniffed under Windows using SnoopyPro.
I _guess_ that 0x22 is a kind of reset command and 0x21
means init..
*/
result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
0x21, 0x42, 0x0001, 0x0002, NULL, 0, 1000);
if (result < 0)
return result;
result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
0x20, 0x42, 0x0001, 0x0002, NULL, 0, 1000);
if (result < 0)
return result;
result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
0x22, 0x42, 0x0000, 0x0002, NULL, 0, 1000);
if (result < 0)
return result;
result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
0x21, 0x42, 0x0001, 0x0002, NULL, 0, 1000);
if (result < 0)
return result;
result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
0x20, 0x42, 0x0001, 0x0002, NULL, 0, 1000);
if (result < 0)
return result;
result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
0x20, 0x42, 0x0000, 0x0002, NULL, 0, 1000);
if (result < 0)
return result;
/* loop over a blocking bulk read to get data from the device */
while (bytes_read < IMGSIZE) {
result = usb_bulk_msg (dev->udev,
usb_rcvbulkpipe (dev->udev, dev->bulk_in_endpointAddr),
dev->bulk_in_buffer + bytes_read,
dev->bulk_in_size, &bulk_read, 5000);
if (result < 0)
return result;
if (signal_pending(current))
return -EINTR;
bytes_read += bulk_read;
}
/* reset the device */
result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
0x22, 0x42, 0x0000, 0x0002, NULL, 0, 1000);
if (result < 0)
return result;
/* should be IMGSIZE == 64815 */
dbg("read %d bytes fingerprint data", bytes_read);
return 0;
}
static inline void idmouse_delete(struct usb_idmouse *dev)
{
kfree(dev->bulk_in_buffer);
kfree(dev);
}
static int idmouse_open(struct inode *inode, struct file *file)
{
struct usb_idmouse *dev = NULL;
struct usb_interface *interface;
int result = 0;
/* prevent disconnects */
down(&disconnect_sem);
/* get the interface from minor number and driver information */
interface = usb_find_interface (&idmouse_driver, iminor (inode));
if (!interface) {
up(&disconnect_sem);
return -ENODEV;
}
/* get the device information block from the interface */
dev = usb_get_intfdata(interface);
if (!dev) {
up(&disconnect_sem);
return -ENODEV;
}
/* lock this device */
down(&dev->sem);
/* check if already open */
if (dev->open) {
/* already open, so fail */
result = -EBUSY;
} else {
/* create a new image and check for success */
result = idmouse_create_image (dev);
if (result)
goto error;
/* increment our usage count for the driver */
++dev->open;
/* save our object in the file's private structure */
file->private_data = dev;
}
error:
/* unlock this device */
up(&dev->sem);
/* unlock the disconnect semaphore */
up(&disconnect_sem);
return result;
}
static int idmouse_release(struct inode *inode, struct file *file)
{
struct usb_idmouse *dev;
/* prevent a race condition with open() */
down(&disconnect_sem);
dev = (struct usb_idmouse *) file->private_data;
if (dev == NULL) {
up(&disconnect_sem);
return -ENODEV;
}
/* lock our device */
down(&dev->sem);
/* are we really open? */
if (dev->open <= 0) {
up(&dev->sem);
up(&disconnect_sem);
return -ENODEV;
}
--dev->open;
if (!dev->present) {
/* the device was unplugged before the file was released */
up(&dev->sem);
idmouse_delete(dev);
up(&disconnect_sem);
return 0;
}
up(&dev->sem);
up(&disconnect_sem);
return 0;
}
static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count,
loff_t * ppos)
{
struct usb_idmouse *dev;
int result = 0;
dev = (struct usb_idmouse *) file->private_data;
// lock this object
down (&dev->sem);
// verify that the device wasn't unplugged
if (!dev->present) {
up (&dev->sem);
return -ENODEV;
}
if (*ppos >= IMGSIZE) {
up (&dev->sem);
return 0;
}
if (count > IMGSIZE - *ppos)
count = IMGSIZE - *ppos;
if (copy_to_user (buffer, dev->bulk_in_buffer + *ppos, count)) {
result = -EFAULT;
} else {
result = count;
*ppos += count;
}
// unlock the device
up(&dev->sem);
return result;
}
static int idmouse_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(interface);
struct usb_idmouse *dev = NULL;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
size_t buffer_size;
int result;
/* check if we have gotten the data or the hid interface */
iface_desc = &interface->altsetting[0];
if (iface_desc->desc.bInterfaceClass != 0x0A)
return -ENODEV;
/* allocate memory for our device state and initialize it */
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL)
return -ENOMEM;
memset(dev, 0x00, sizeof(*dev));
init_MUTEX(&dev->sem);
dev->udev = udev;
dev->interface = interface;
/* set up the endpoint information - use only the first bulk-in endpoint */
endpoint = &iface_desc->endpoint[0].desc;
if (!dev->bulk_in_endpointAddr
&& (endpoint->bEndpointAddress & USB_DIR_IN)
&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
/* we found a bulk in endpoint */
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
dev->bulk_in_size = buffer_size;
dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
dev->bulk_in_buffer =
kmalloc(IMGSIZE + buffer_size, GFP_KERNEL);
if (!dev->bulk_in_buffer) {
err("Unable to allocate input buffer.");
idmouse_delete(dev);
return -ENOMEM;
}
}
if (!(dev->bulk_in_endpointAddr)) {
err("Unable to find bulk-in endpoint.");
idmouse_delete(dev);
return -ENODEV;
}
/* allow device read, write and ioctl */
dev->present = 1;
/* we can register the device now, as it is ready */
usb_set_intfdata(interface, dev);
result = usb_register_dev(interface, &idmouse_class);
if (result) {
/* something prevented us from registering this device */
err("Unble to allocate minor number.");
usb_set_intfdata(interface, NULL);
idmouse_delete(dev);
return result;
}
/* be noisy */
dev_info(&interface->dev,"%s now attached\n",DRIVER_DESC);
return 0;
}
static void idmouse_disconnect(struct usb_interface *interface)
{
struct usb_idmouse *dev;
/* prevent races with open() */
down(&disconnect_sem);
/* get device structure */
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
/* lock it */
down(&dev->sem);
/* give back our minor */
usb_deregister_dev(interface, &idmouse_class);
/* prevent device read, write and ioctl */
dev->present = 0;
/* unlock */
up(&dev->sem);
/* if the device is opened, idmouse_release will clean this up */
if (!dev->open)
idmouse_delete(dev);
up(&disconnect_sem);
info("%s disconnected", DRIVER_DESC);
}
static int __init usb_idmouse_init(void)
{
int result;
info(DRIVER_DESC " " DRIVER_VERSION);
/* register this driver with the USB subsystem */
result = usb_register(&idmouse_driver);
if (result)
err("Unable to register device (error %d).", result);
return result;
}
static void __exit usb_idmouse_exit(void)
{
/* deregister this driver with the USB subsystem */
usb_deregister(&idmouse_driver);
}
module_init(usb_idmouse_init);
module_exit(usb_idmouse_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

文件差異過大導致無法顯示 Load Diff

查看文件

@@ -0,0 +1,586 @@
/*
* USB PhidgetInterfaceKit driver 1.0
*
* Copyright (C) 2004 Sean Young <sean@mess.org>
* Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
*
* 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.
*
* This is a driver for the USB PhidgetInterfaceKit.
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/usb.h>
#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
#define DRIVER_DESC "USB PhidgetInterfaceKit Driver"
#define USB_VENDOR_ID_GLAB 0x06c2
#define USB_DEVICE_ID_INTERFACEKIT004 0x0040
#define USB_DEVICE_ID_INTERFACEKIT888 0x0045
#define USB_DEVICE_ID_INTERFACEKIT047 0x0051
#define USB_DEVICE_ID_INTERFACEKIT088 0x0053
#define USB_VENDOR_ID_WISEGROUP 0x0925
#define USB_DEVICE_ID_INTERFACEKIT884 0x8201
#define MAX_INTERFACES 8
struct driver_interfacekit {
int sensors;
int inputs;
int outputs;
int has_lcd;
};
#define ifkit(_sensors, _inputs, _outputs, _lcd) \
static struct driver_interfacekit ph_##_sensors##_inputs##_outputs = { \
.sensors = _sensors, \
.inputs = _inputs, \
.outputs = _outputs, \
.has_lcd = _lcd, \
};
ifkit(0, 0, 4, 0);
ifkit(8, 8, 8, 0);
ifkit(0, 4, 7, 1);
ifkit(8, 8, 4, 0);
ifkit(0, 8, 8, 1);
struct phidget_interfacekit {
struct usb_device *udev;
struct usb_interface *intf;
struct driver_interfacekit *ifkit;
int outputs[MAX_INTERFACES];
int inputs[MAX_INTERFACES];
int sensors[MAX_INTERFACES];
u8 lcd_files_on;
struct urb *irq;
unsigned char *data;
dma_addr_t data_dma;
};
static struct usb_device_id id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004),
.driver_info = (kernel_ulong_t)&ph_004},
{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888),
.driver_info = (kernel_ulong_t)&ph_888},
{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047),
.driver_info = (kernel_ulong_t)&ph_047},
{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088),
.driver_info = (kernel_ulong_t)&ph_088},
{USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884),
.driver_info = (kernel_ulong_t)&ph_884},
{}
};
MODULE_DEVICE_TABLE(usb, id_table);
static int change_outputs(struct phidget_interfacekit *kit, int output_num, int enable)
{
unsigned char *buffer;
int retval;
int n;
buffer = kmalloc(4, GFP_KERNEL);
if (!buffer) {
dev_err(&kit->udev->dev, "%s - out of memory\n",
__FUNCTION__);
return -ENOMEM;
}
kit->outputs[output_num] = enable;
memset(buffer, 0, 4);
for (n=0; n<8; n++) {
if (kit->outputs[n]) {
buffer[0] |= 1 << n;
}
}
dev_dbg(&kit->udev->dev, "sending data: %02x\n", buffer[0]);
retval = usb_control_msg(kit->udev,
usb_sndctrlpipe(kit->udev, 0),
0x09, 0x21, 0x0200, 0x0000, buffer, 4, 2000);
if (retval != 4)
dev_err(&kit->udev->dev, "usb_control_msg returned %d\n",
retval);
kfree(buffer);
return retval < 0 ? retval : 0;
}
static int change_string(struct phidget_interfacekit *kit, const char *display, unsigned char row)
{
unsigned char *buffer;
unsigned char *form_buffer;
int retval = -ENOMEM;
int i,j, len, buf_ptr;
buffer = kmalloc(8, GFP_KERNEL);
form_buffer = kmalloc(30, GFP_KERNEL);
if ((!buffer) || (!form_buffer)) {
dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
goto exit;
}
len = strlen(display);
if (len > 20)
len = 20;
dev_dbg(&kit->udev->dev, "Setting LCD line %d to %s\n", row, display);
form_buffer[0] = row * 0x40 + 0x80;
form_buffer[1] = 0x02;
buf_ptr = 2;
for (i = 0; i<len; i++)
form_buffer[buf_ptr++] = display[i];
for (i = 0; i < (20 - len); i++)
form_buffer[buf_ptr++] = 0x20;
form_buffer[buf_ptr++] = 0x01;
form_buffer[buf_ptr++] = row * 0x40 + 0x80 + strlen(display);
for (i = 0; i < buf_ptr; i += 7) {
if ((buf_ptr - i) > 7)
len = 7;
else
len = (buf_ptr - i);
for (j = 0; j < len; j++)
buffer[j] = form_buffer[i + j];
buffer[7] = len;
retval = usb_control_msg(kit->udev,
usb_sndctrlpipe(kit->udev, 0),
0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
if (retval < 0)
goto exit;
}
retval = 0;
exit:
kfree(buffer);
kfree(form_buffer);
return retval;
}
#define set_lcd_line(number) \
static ssize_t lcd_line_##number(struct device *dev, const char *buf, size_t count) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
change_string(kit, buf, number - 1); \
return count; \
} \
static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number);
set_lcd_line(1);
set_lcd_line(2);
static ssize_t set_backlight(struct device *dev, const char *buf, size_t count)
{
struct usb_interface *intf = to_usb_interface(dev);
struct phidget_interfacekit *kit = usb_get_intfdata(intf);
int enabled;
unsigned char *buffer;
int retval = -ENOMEM;
buffer = kmalloc(8, GFP_KERNEL);
if (!buffer) {
dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
goto exit;
}
if (sscanf(buf, "%d", &enabled) < 1) {
retval = -EINVAL;
goto exit;
}
memset(buffer, 0x00, 8);
if (enabled)
buffer[0] = 0x01;
buffer[7] = 0x11;
dev_dbg(&kit->udev->dev, "Setting backlight to %s\n", enabled ? "on" : "off");
retval = usb_control_msg(kit->udev,
usb_sndctrlpipe(kit->udev, 0),
0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
if (retval < 0)
goto exit;
retval = count;
exit:
kfree(buffer);
return retval;
}
static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight);
static void remove_lcd_files(struct phidget_interfacekit *kit)
{
if (kit->lcd_files_on) {
dev_dbg(&kit->udev->dev, "Removing lcd files\n");
device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_1);
device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_2);
device_remove_file(&kit->intf->dev, &dev_attr_backlight);
}
}
static ssize_t enable_lcd_files(struct device *dev, const char *buf, size_t count)
{
struct usb_interface *intf = to_usb_interface(dev);
struct phidget_interfacekit *kit = usb_get_intfdata(intf);
int enable;
if (kit->ifkit->has_lcd == 0)
return -ENODEV;
if (sscanf(buf, "%d", &enable) < 1)
return -EINVAL;
if (enable) {
if (!kit->lcd_files_on) {
dev_dbg(&kit->udev->dev, "Adding lcd files\n");
device_create_file(&kit->intf->dev, &dev_attr_lcd_line_1);
device_create_file(&kit->intf->dev, &dev_attr_lcd_line_2);
device_create_file(&kit->intf->dev, &dev_attr_backlight);
kit->lcd_files_on = 1;
}
} else {
if (kit->lcd_files_on) {
remove_lcd_files(kit);
kit->lcd_files_on = 0;
}
}
return count;
}
static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files);
static void interfacekit_irq(struct urb *urb, struct pt_regs *regs)
{
struct phidget_interfacekit *kit = urb->context;
unsigned char *buffer = kit->data;
int status;
int n;
switch (urb->status) {
case 0: /* success */
break;
case -ECONNRESET: /* unlink */
case -ENOENT:
case -ESHUTDOWN:
return;
/* -EPIPE: should clear the halt */
default: /* error */
goto resubmit;
}
for (n=0; n<8; n++) {
kit->inputs[n] = buffer[1] & (1 << n) ? 1 : 0;
}
if (buffer[0] & 1) {
kit->sensors[4] = buffer[2] + (buffer[3] & 0x0f) * 256;
kit->sensors[5] = buffer[4] + (buffer[3] & 0xf0) * 16;
kit->sensors[6] = buffer[5] + (buffer[6] & 0x0f) * 256;
kit->sensors[7] = buffer[7] + (buffer[6] & 0xf0) * 16;
} else {
kit->sensors[0] = buffer[2] + (buffer[3] & 0x0f) * 256;
kit->sensors[1] = buffer[4] + (buffer[3] & 0xf0) * 16;
kit->sensors[2] = buffer[5] + (buffer[6] & 0x0f) * 256;
kit->sensors[3] = buffer[7] + (buffer[6] & 0xf0) * 16;
}
resubmit:
status = usb_submit_urb(urb, SLAB_ATOMIC);
if (status)
err("can't resubmit intr, %s-%s/interfacekit0, status %d",
kit->udev->bus->bus_name,
kit->udev->devpath, status);
}
#define show_set_output(value) \
static ssize_t set_output##value(struct device *dev, const char *buf, \
size_t count) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
int enabled; \
int retval; \
\
if (sscanf(buf, "%d", &enabled) < 1) { \
return -EINVAL; \
} \
\
retval = change_outputs(kit, value - 1, enabled ? 1 : 0); \
\
return retval ? retval : count; \
} \
\
static ssize_t show_output##value(struct device *dev, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
\
return sprintf(buf, "%d\n", kit->outputs[value - 1]); \
} \
static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO, \
show_output##value, set_output##value);
show_set_output(1);
show_set_output(2);
show_set_output(3);
show_set_output(4);
show_set_output(5);
show_set_output(6);
show_set_output(7);
show_set_output(8); /* should be MAX_INTERFACES - 1 */
#define show_input(value) \
static ssize_t show_input##value(struct device *dev, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
\
return sprintf(buf, "%d\n", kit->inputs[value - 1]); \
} \
static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL);
show_input(1);
show_input(2);
show_input(3);
show_input(4);
show_input(5);
show_input(6);
show_input(7);
show_input(8); /* should be MAX_INTERFACES - 1 */
#define show_sensor(value) \
static ssize_t show_sensor##value(struct device *dev, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
\
return sprintf(buf, "%d\n", kit->sensors[value - 1]); \
} \
static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL);
show_sensor(1);
show_sensor(2);
show_sensor(3);
show_sensor(4);
show_sensor(5);
show_sensor(6);
show_sensor(7);
show_sensor(8); /* should be MAX_INTERFACES - 1 */
static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct phidget_interfacekit *kit;
struct driver_interfacekit *ifkit;
int pipe, maxp;
ifkit = (struct driver_interfacekit *)id->driver_info;
if (!ifkit)
return -ENODEV;
interface = intf->cur_altsetting;
if (interface->desc.bNumEndpoints != 1)
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
if (!(endpoint->bEndpointAddress & 0x80))
return -ENODEV;
/*
* bmAttributes
*/
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
kit = kmalloc(sizeof(*kit), GFP_KERNEL);
if (kit == NULL) {
dev_err(&intf->dev, "%s - out of memory\n", __FUNCTION__);
return -ENOMEM;
}
memset(kit, 0, sizeof(*kit));
kit->ifkit = ifkit;
kit->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kit->data_dma);
if (!kit->data) {
kfree(kit);
return -ENOMEM;
}
kit->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!kit->irq) {
usb_buffer_free(dev, 8, kit->data, kit->data_dma);
kfree(kit);
return -ENOMEM;
}
kit->udev = usb_get_dev(dev);
kit->intf = intf;
usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data,
(maxp > 8 ? 8 : maxp),
interfacekit_irq, kit, endpoint->bInterval);
kit->irq->transfer_dma = kit->data_dma;
kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
usb_set_intfdata(intf, kit);
if (usb_submit_urb(kit->irq, GFP_KERNEL)) {
return -EIO;
}
if (ifkit->outputs >= 4) {
device_create_file(&intf->dev, &dev_attr_output1);
device_create_file(&intf->dev, &dev_attr_output2);
device_create_file(&intf->dev, &dev_attr_output3);
device_create_file(&intf->dev, &dev_attr_output4);
}
if (ifkit->outputs == 8) {
device_create_file(&intf->dev, &dev_attr_output5);
device_create_file(&intf->dev, &dev_attr_output6);
device_create_file(&intf->dev, &dev_attr_output7);
device_create_file(&intf->dev, &dev_attr_output8);
}
if (ifkit->inputs >= 4) {
device_create_file(&intf->dev, &dev_attr_input1);
device_create_file(&intf->dev, &dev_attr_input2);
device_create_file(&intf->dev, &dev_attr_input3);
device_create_file(&intf->dev, &dev_attr_input4);
}
if (ifkit->inputs == 8) {
device_create_file(&intf->dev, &dev_attr_input5);
device_create_file(&intf->dev, &dev_attr_input6);
device_create_file(&intf->dev, &dev_attr_input7);
device_create_file(&intf->dev, &dev_attr_input8);
}
if (ifkit->sensors >= 4) {
device_create_file(&intf->dev, &dev_attr_sensor1);
device_create_file(&intf->dev, &dev_attr_sensor2);
device_create_file(&intf->dev, &dev_attr_sensor3);
device_create_file(&intf->dev, &dev_attr_sensor4);
}
if (ifkit->sensors >= 7) {
device_create_file(&intf->dev, &dev_attr_sensor5);
device_create_file(&intf->dev, &dev_attr_sensor6);
device_create_file(&intf->dev, &dev_attr_sensor7);
}
if (ifkit->sensors == 8) {
device_create_file(&intf->dev, &dev_attr_sensor8);
}
if (ifkit->has_lcd)
device_create_file(&intf->dev, &dev_attr_lcd);
dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n",
ifkit->sensors, ifkit->inputs, ifkit->outputs);
return 0;
}
static void interfacekit_disconnect(struct usb_interface *interface)
{
struct phidget_interfacekit *kit;
kit = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
if (!kit)
return;
if (kit->ifkit->outputs >= 4) {
device_remove_file(&interface->dev, &dev_attr_output1);
device_remove_file(&interface->dev, &dev_attr_output2);
device_remove_file(&interface->dev, &dev_attr_output3);
device_remove_file(&interface->dev, &dev_attr_output4);
}
if (kit->ifkit->outputs == 8) {
device_remove_file(&interface->dev, &dev_attr_output5);
device_remove_file(&interface->dev, &dev_attr_output6);
device_remove_file(&interface->dev, &dev_attr_output7);
device_remove_file(&interface->dev, &dev_attr_output8);
}
if (kit->ifkit->inputs >= 4) {
device_remove_file(&interface->dev, &dev_attr_input1);
device_remove_file(&interface->dev, &dev_attr_input2);
device_remove_file(&interface->dev, &dev_attr_input3);
device_remove_file(&interface->dev, &dev_attr_input4);
}
if (kit->ifkit->inputs == 8) {
device_remove_file(&interface->dev, &dev_attr_input5);
device_remove_file(&interface->dev, &dev_attr_input6);
device_remove_file(&interface->dev, &dev_attr_input7);
device_remove_file(&interface->dev, &dev_attr_input8);
}
if (kit->ifkit->sensors >= 4) {
device_remove_file(&interface->dev, &dev_attr_sensor1);
device_remove_file(&interface->dev, &dev_attr_sensor2);
device_remove_file(&interface->dev, &dev_attr_sensor3);
device_remove_file(&interface->dev, &dev_attr_sensor4);
}
if (kit->ifkit->sensors >= 7) {
device_remove_file(&interface->dev, &dev_attr_sensor5);
device_remove_file(&interface->dev, &dev_attr_sensor6);
device_remove_file(&interface->dev, &dev_attr_sensor7);
}
if (kit->ifkit->sensors == 8) {
device_remove_file(&interface->dev, &dev_attr_sensor8);
}
if (kit->ifkit->has_lcd)
device_remove_file(&interface->dev, &dev_attr_lcd);
dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n",
kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs);
usb_kill_urb(kit->irq);
usb_free_urb(kit->irq);
usb_buffer_free(kit->udev, 8, kit->data, kit->data_dma);
usb_put_dev(kit->udev);
kfree(kit);
}
static struct usb_driver interfacekit_driver = {
.owner = THIS_MODULE,
.name = "phidgetkit",
.probe = interfacekit_probe,
.disconnect = interfacekit_disconnect,
.id_table = id_table
};
static int __init interfacekit_init(void)
{
int retval = 0;
retval = usb_register(&interfacekit_driver);
if (retval)
err("usb_register failed. Error number %d", retval);
return retval;
}
static void __exit interfacekit_exit(void)
{
usb_deregister(&interfacekit_driver);
}
module_init(interfacekit_init);
module_exit(interfacekit_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

查看文件

@@ -0,0 +1,342 @@
/*
* USB PhidgetServo driver 1.0
*
* Copyright (C) 2004 Sean Young <sean@mess.org>
*
* 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.
*
* This is a driver for the USB PhidgetServo version 2.0 and 3.0 servo
* controllers available at: http://www.phidgets.com/
*
* Note that the driver takes input as: degrees.minutes
*
* CAUTION: Generally you should use 0 < degrees < 180 as anything else
* is probably beyond the range of your servo and may damage it.
*
* Jun 16, 2004: Sean Young <sean@mess.org>
* - cleanups
* - was using memory after kfree()
* Aug 8, 2004: Sean Young <sean@mess.org>
* - set the highest angle as high as the hardware allows, there are
* some odd servos out there
*
*/
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/usb.h>
#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
#define DRIVER_DESC "USB PhidgetServo Driver"
#define VENDOR_ID_GLAB 0x06c2
#define DEVICE_ID_GLAB_PHIDGETSERVO_QUAD 0x0038
#define DEVICE_ID_GLAB_PHIDGETSERVO_UNI 0x0039
#define VENDOR_ID_WISEGROUP 0x0925
#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD 0x8101
#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI 0x8104
#define SERVO_VERSION_30 0x01
#define SERVO_COUNT_QUAD 0x02
static struct usb_device_id id_table[] = {
{
USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_QUAD),
.driver_info = SERVO_VERSION_30 | SERVO_COUNT_QUAD
},
{
USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_UNI),
.driver_info = SERVO_VERSION_30
},
{
USB_DEVICE(VENDOR_ID_WISEGROUP,
VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD),
.driver_info = SERVO_COUNT_QUAD
},
{
USB_DEVICE(VENDOR_ID_WISEGROUP,
VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI),
.driver_info = 0
},
{}
};
MODULE_DEVICE_TABLE(usb, id_table);
struct phidget_servo {
struct usb_device *udev;
ulong type;
int pulse[4];
int degrees[4];
int minutes[4];
};
static int
change_position_v30(struct phidget_servo *servo, int servo_no, int degrees,
int minutes)
{
int retval;
unsigned char *buffer;
if (degrees < -23 || degrees > 362)
return -EINVAL;
buffer = kmalloc(6, GFP_KERNEL);
if (!buffer) {
dev_err(&servo->udev->dev, "%s - out of memory\n",
__FUNCTION__);
return -ENOMEM;
}
/*
* pulse = 0 - 4095
* angle = 0 - 180 degrees
*
* pulse = angle * 10.6 + 243.8
*/
servo->pulse[servo_no] = ((degrees*60 + minutes)*106 + 2438*60)/600;
servo->degrees[servo_no]= degrees;
servo->minutes[servo_no]= minutes;
/*
* The PhidgetServo v3.0 is controlled by sending 6 bytes,
* 4 * 12 bits for each servo.
*
* low = lower 8 bits pulse
* high = higher 4 bits pulse
*
* offset bits
* +---+-----------------+
* | 0 | low 0 |
* +---+--------+--------+
* | 1 | high 1 | high 0 |
* +---+--------+--------+
* | 2 | low 1 |
* +---+-----------------+
* | 3 | low 2 |
* +---+--------+--------+
* | 4 | high 3 | high 2 |
* +---+--------+--------+
* | 5 | low 3 |
* +---+-----------------+
*/
buffer[0] = servo->pulse[0] & 0xff;
buffer[1] = (servo->pulse[0] >> 8 & 0x0f)
| (servo->pulse[1] >> 4 & 0xf0);
buffer[2] = servo->pulse[1] & 0xff;
buffer[3] = servo->pulse[2] & 0xff;
buffer[4] = (servo->pulse[2] >> 8 & 0x0f)
| (servo->pulse[3] >> 4 & 0xf0);
buffer[5] = servo->pulse[3] & 0xff;
dev_dbg(&servo->udev->dev,
"data: %02x %02x %02x %02x %02x %02x\n",
buffer[0], buffer[1], buffer[2],
buffer[3], buffer[4], buffer[5]);
retval = usb_control_msg(servo->udev,
usb_sndctrlpipe(servo->udev, 0),
0x09, 0x21, 0x0200, 0x0000, buffer, 6, 2000);
kfree(buffer);
return retval;
}
static int
change_position_v20(struct phidget_servo *servo, int servo_no, int degrees,
int minutes)
{
int retval;
unsigned char *buffer;
if (degrees < -23 || degrees > 278)
return -EINVAL;
buffer = kmalloc(2, GFP_KERNEL);
if (!buffer) {
dev_err(&servo->udev->dev, "%s - out of memory\n",
__FUNCTION__);
return -ENOMEM;
}
/*
* angle = 0 - 180 degrees
* pulse = angle + 23
*/
servo->pulse[servo_no]= degrees + 23;
servo->degrees[servo_no]= degrees;
servo->minutes[servo_no]= 0;
/*
* The PhidgetServo v2.0 is controlled by sending two bytes. The
* first byte is the servo number xor'ed with 2:
*
* servo 0 = 2
* servo 1 = 3
* servo 2 = 0
* servo 3 = 1
*
* The second byte is the position.
*/
buffer[0] = servo_no ^ 2;
buffer[1] = servo->pulse[servo_no];
dev_dbg(&servo->udev->dev, "data: %02x %02x\n", buffer[0], buffer[1]);
retval = usb_control_msg(servo->udev,
usb_sndctrlpipe(servo->udev, 0),
0x09, 0x21, 0x0200, 0x0000, buffer, 2, 2000);
kfree(buffer);
return retval;
}
#define show_set(value) \
static ssize_t set_servo##value (struct device *dev, \
const char *buf, size_t count) \
{ \
int degrees, minutes, retval; \
struct usb_interface *intf = to_usb_interface (dev); \
struct phidget_servo *servo = usb_get_intfdata (intf); \
\
minutes = 0; \
/* must at least convert degrees */ \
if (sscanf (buf, "%d.%d", &degrees, &minutes) < 1) { \
return -EINVAL; \
} \
\
if (minutes < 0 || minutes > 59) \
return -EINVAL; \
\
if (servo->type & SERVO_VERSION_30) \
retval = change_position_v30 (servo, value, degrees, \
minutes); \
else \
retval = change_position_v20 (servo, value, degrees, \
minutes); \
\
return retval < 0 ? retval : count; \
} \
\
static ssize_t show_servo##value (struct device *dev, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface (dev); \
struct phidget_servo *servo = usb_get_intfdata (intf); \
\
return sprintf (buf, "%d.%02d\n", servo->degrees[value], \
servo->minutes[value]); \
} \
static DEVICE_ATTR(servo##value, S_IWUGO | S_IRUGO, \
show_servo##value, set_servo##value);
show_set(0);
show_set(1);
show_set(2);
show_set(3);
static int
servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(interface);
struct phidget_servo *dev;
dev = kmalloc(sizeof (struct phidget_servo), GFP_KERNEL);
if (dev == NULL) {
dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
return -ENOMEM;
}
memset(dev, 0x00, sizeof (*dev));
dev->udev = usb_get_dev(udev);
dev->type = id->driver_info;
usb_set_intfdata(interface, dev);
device_create_file(&interface->dev, &dev_attr_servo0);
if (dev->type & SERVO_COUNT_QUAD) {
device_create_file(&interface->dev, &dev_attr_servo1);
device_create_file(&interface->dev, &dev_attr_servo2);
device_create_file(&interface->dev, &dev_attr_servo3);
}
dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n",
dev->type & SERVO_COUNT_QUAD ? 4 : 1,
dev->type & SERVO_VERSION_30 ? 3 : 2);
if(!(dev->type & SERVO_VERSION_30))
dev_info(&interface->dev,
"WARNING: v2.0 not tested! Please report if it works.\n");
return 0;
}
static void
servo_disconnect(struct usb_interface *interface)
{
struct phidget_servo *dev;
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
device_remove_file(&interface->dev, &dev_attr_servo0);
if (dev->type & SERVO_COUNT_QUAD) {
device_remove_file(&interface->dev, &dev_attr_servo1);
device_remove_file(&interface->dev, &dev_attr_servo2);
device_remove_file(&interface->dev, &dev_attr_servo3);
}
usb_put_dev(dev->udev);
dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n",
dev->type & SERVO_COUNT_QUAD ? 4 : 1,
dev->type & SERVO_VERSION_30 ? 3 : 2);
kfree(dev);
}
static struct usb_driver servo_driver = {
.owner = THIS_MODULE,
.name = "phidgetservo",
.probe = servo_probe,
.disconnect = servo_disconnect,
.id_table = id_table
};
static int __init
phidget_servo_init(void)
{
int retval;
retval = usb_register(&servo_driver);
if (retval)
err("usb_register failed. Error number %d", retval);
return retval;
}
static void __exit
phidget_servo_exit(void)
{
usb_deregister(&servo_driver);
}
module_init(phidget_servo_init);
module_exit(phidget_servo_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

563
drivers/usb/misc/rio500.c Normal file
查看文件

@@ -0,0 +1,563 @@
/* -*- linux-c -*- */
/*
* Driver for USB Rio 500
*
* Cesar Miquel (miquel@df.uba.ar)
*
* based on hp_scanner.c by David E. Nelson (dnelson@jump.net)
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee).
*
* Changelog:
* 30/05/2003 replaced lock/unlock kernel with up/down
* Daniele Bellucci bellucda@tiscali.it
* */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/smp_lock.h>
#include <linux/wait.h>
#include "rio500_usb.h"
/*
* Version Information
*/
#define DRIVER_VERSION "v1.1"
#define DRIVER_AUTHOR "Cesar Miquel <miquel@df.uba.ar>"
#define DRIVER_DESC "USB Rio 500 driver"
#define RIO_MINOR 64
/* stall/wait timeout for rio */
#define NAK_TIMEOUT (HZ)
#define IBUF_SIZE 0x1000
/* Size of the rio buffer */
#define OBUF_SIZE 0x10000
struct rio_usb_data {
struct usb_device *rio_dev; /* init: probe_rio */
unsigned int ifnum; /* Interface number of the USB device */
int isopen; /* nz if open */
int present; /* Device is present on the bus */
char *obuf, *ibuf; /* transfer buffers */
char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */
wait_queue_head_t wait_q; /* for timeouts */
struct semaphore lock; /* general race avoidance */
};
static struct rio_usb_data rio_instance;
static int open_rio(struct inode *inode, struct file *file)
{
struct rio_usb_data *rio = &rio_instance;
down(&(rio->lock));
if (rio->isopen || !rio->present) {
up(&(rio->lock));
return -EBUSY;
}
rio->isopen = 1;
init_waitqueue_head(&rio->wait_q);
up(&(rio->lock));
info("Rio opened.");
return 0;
}
static int close_rio(struct inode *inode, struct file *file)
{
struct rio_usb_data *rio = &rio_instance;
rio->isopen = 0;
info("Rio closed.");
return 0;
}
static int
ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
struct RioCommand rio_cmd;
struct rio_usb_data *rio = &rio_instance;
void __user *data;
unsigned char *buffer;
int result, requesttype;
int retries;
int retval=0;
down(&(rio->lock));
/* Sanity check to make sure rio is connected, powered, etc */
if ( rio == NULL ||
rio->present == 0 ||
rio->rio_dev == NULL )
{
retval = -ENODEV;
goto err_out;
}
switch (cmd) {
case RIO_RECV_COMMAND:
data = (void __user *) arg;
if (data == NULL)
break;
if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) {
retval = -EFAULT;
goto err_out;
}
if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) {
retval = -EINVAL;
goto err_out;
}
buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
if (buffer == NULL) {
retval = -ENOMEM;
goto err_out;
}
if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) {
retval = -EFAULT;
free_page((unsigned long) buffer);
goto err_out;
}
requesttype = rio_cmd.requesttype | USB_DIR_IN |
USB_TYPE_VENDOR | USB_RECIP_DEVICE;
dbg
("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x",
requesttype, rio_cmd.request, rio_cmd.value,
rio_cmd.index, rio_cmd.length);
/* Send rio control message */
retries = 3;
while (retries) {
result = usb_control_msg(rio->rio_dev,
usb_rcvctrlpipe(rio-> rio_dev, 0),
rio_cmd.request,
requesttype,
rio_cmd.value,
rio_cmd.index, buffer,
rio_cmd.length,
jiffies_to_msecs(rio_cmd.timeout));
if (result == -ETIMEDOUT)
retries--;
else if (result < 0) {
err("Error executing ioctrl. code = %d", result);
retries = 0;
} else {
dbg("Executed ioctl. Result = %d (data=%02x)",
result, buffer[0]);
if (copy_to_user(rio_cmd.buffer, buffer,
rio_cmd.length)) {
free_page((unsigned long) buffer);
retval = -EFAULT;
goto err_out;
}
retries = 0;
}
/* rio_cmd.buffer contains a raw stream of single byte
data which has been returned from rio. Data is
interpreted at application level. For data that
will be cast to data types longer than 1 byte, data
will be little_endian and will potentially need to
be swapped at the app level */
}
free_page((unsigned long) buffer);
break;
case RIO_SEND_COMMAND:
data = (void __user *) arg;
if (data == NULL)
break;
if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) {
retval = -EFAULT;
goto err_out;
}
if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) {
retval = -EINVAL;
goto err_out;
}
buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
if (buffer == NULL) {
retval = -ENOMEM;
goto err_out;
}
if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) {
free_page((unsigned long)buffer);
retval = -EFAULT;
goto err_out;
}
requesttype = rio_cmd.requesttype | USB_DIR_OUT |
USB_TYPE_VENDOR | USB_RECIP_DEVICE;
dbg("sending command: reqtype=%0x req=%0x value=%0x index=%0x len=%0x",
requesttype, rio_cmd.request, rio_cmd.value,
rio_cmd.index, rio_cmd.length);
/* Send rio control message */
retries = 3;
while (retries) {
result = usb_control_msg(rio->rio_dev,
usb_sndctrlpipe(rio-> rio_dev, 0),
rio_cmd.request,
requesttype,
rio_cmd.value,
rio_cmd.index, buffer,
rio_cmd.length,
jiffies_to_msecs(rio_cmd.timeout));
if (result == -ETIMEDOUT)
retries--;
else if (result < 0) {
err("Error executing ioctrl. code = %d", result);
retries = 0;
} else {
dbg("Executed ioctl. Result = %d", result);
retries = 0;
}
}
free_page((unsigned long) buffer);
break;
default:
retval = -ENOTTY;
break;
}
err_out:
up(&(rio->lock));
return retval;
}
static ssize_t
write_rio(struct file *file, const char __user *buffer,
size_t count, loff_t * ppos)
{
DEFINE_WAIT(wait);
struct rio_usb_data *rio = &rio_instance;
unsigned long copy_size;
unsigned long bytes_written = 0;
unsigned int partial;
int result = 0;
int maxretry;
int errn = 0;
down(&(rio->lock));
/* Sanity check to make sure rio is connected, powered, etc */
if ( rio == NULL ||
rio->present == 0 ||
rio->rio_dev == NULL )
{
up(&(rio->lock));
return -ENODEV;
}
do {
unsigned long thistime;
char *obuf = rio->obuf;
thistime = copy_size =
(count >= OBUF_SIZE) ? OBUF_SIZE : count;
if (copy_from_user(rio->obuf, buffer, copy_size)) {
errn = -EFAULT;
goto error;
}
maxretry = 5;
while (thistime) {
if (!rio->rio_dev) {
errn = -ENODEV;
goto error;
}
if (signal_pending(current)) {
up(&(rio->lock));
return bytes_written ? bytes_written : -EINTR;
}
result = usb_bulk_msg(rio->rio_dev,
usb_sndbulkpipe(rio->rio_dev, 2),
obuf, thistime, &partial, 5000);
dbg("write stats: result:%d thistime:%lu partial:%u",
result, thistime, partial);
if (result == -ETIMEDOUT) { /* NAK - so hold for a while */
if (!maxretry--) {
errn = -ETIME;
goto error;
}
prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE);
schedule_timeout(NAK_TIMEOUT);
finish_wait(&rio->wait_q, &wait);
continue;
} else if (!result && partial) {
obuf += partial;
thistime -= partial;
} else
break;
};
if (result) {
err("Write Whoops - %x", result);
errn = -EIO;
goto error;
}
bytes_written += copy_size;
count -= copy_size;
buffer += copy_size;
} while (count > 0);
up(&(rio->lock));
return bytes_written ? bytes_written : -EIO;
error:
up(&(rio->lock));
return errn;
}
static ssize_t
read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
{
DEFINE_WAIT(wait);
struct rio_usb_data *rio = &rio_instance;
ssize_t read_count;
unsigned int partial;
int this_read;
int result;
int maxretry = 10;
char *ibuf;
down(&(rio->lock));
/* Sanity check to make sure rio is connected, powered, etc */
if ( rio == NULL ||
rio->present == 0 ||
rio->rio_dev == NULL )
{
up(&(rio->lock));
return -ENODEV;
}
ibuf = rio->ibuf;
read_count = 0;
while (count > 0) {
if (signal_pending(current)) {
up(&(rio->lock));
return read_count ? read_count : -EINTR;
}
if (!rio->rio_dev) {
up(&(rio->lock));
return -ENODEV;
}
this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
result = usb_bulk_msg(rio->rio_dev,
usb_rcvbulkpipe(rio->rio_dev, 1),
ibuf, this_read, &partial,
8000);
dbg(KERN_DEBUG "read stats: result:%d this_read:%u partial:%u",
result, this_read, partial);
if (partial) {
count = this_read = partial;
} else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */
if (!maxretry--) {
up(&(rio->lock));
err("read_rio: maxretry timeout");
return -ETIME;
}
prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE);
schedule_timeout(NAK_TIMEOUT);
finish_wait(&rio->wait_q, &wait);
continue;
} else if (result != -EREMOTEIO) {
up(&(rio->lock));
err("Read Whoops - result:%u partial:%u this_read:%u",
result, partial, this_read);
return -EIO;
} else {
up(&(rio->lock));
return (0);
}
if (this_read) {
if (copy_to_user(buffer, ibuf, this_read)) {
up(&(rio->lock));
return -EFAULT;
}
count -= this_read;
read_count += this_read;
buffer += this_read;
}
}
up(&(rio->lock));
return read_count;
}
static struct
file_operations usb_rio_fops = {
.owner = THIS_MODULE,
.read = read_rio,
.write = write_rio,
.ioctl = ioctl_rio,
.open = open_rio,
.release = close_rio,
};
static struct usb_class_driver usb_rio_class = {
.name = "usb/rio500%d",
.fops = &usb_rio_fops,
.mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
.minor_base = RIO_MINOR,
};
static int probe_rio(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
struct rio_usb_data *rio = &rio_instance;
int retval;
info("USB Rio found at address %d", dev->devnum);
retval = usb_register_dev(intf, &usb_rio_class);
if (retval) {
err("Not able to get a minor for this device.");
return -ENOMEM;
}
rio->rio_dev = dev;
if (!(rio->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
err("probe_rio: Not enough memory for the output buffer");
usb_deregister_dev(intf, &usb_rio_class);
return -ENOMEM;
}
dbg("probe_rio: obuf address:%p", rio->obuf);
if (!(rio->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) {
err("probe_rio: Not enough memory for the input buffer");
usb_deregister_dev(intf, &usb_rio_class);
kfree(rio->obuf);
return -ENOMEM;
}
dbg("probe_rio: ibuf address:%p", rio->ibuf);
init_MUTEX(&(rio->lock));
usb_set_intfdata (intf, rio);
rio->present = 1;
return 0;
}
static void disconnect_rio(struct usb_interface *intf)
{
struct rio_usb_data *rio = usb_get_intfdata (intf);
usb_set_intfdata (intf, NULL);
if (rio) {
usb_deregister_dev(intf, &usb_rio_class);
down(&(rio->lock));
if (rio->isopen) {
rio->isopen = 0;
/* better let it finish - the release will do whats needed */
rio->rio_dev = NULL;
up(&(rio->lock));
return;
}
kfree(rio->ibuf);
kfree(rio->obuf);
info("USB Rio disconnected.");
rio->present = 0;
up(&(rio->lock));
}
}
static struct usb_device_id rio_table [] = {
{ USB_DEVICE(0x0841, 1) }, /* Rio 500 */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, rio_table);
static struct usb_driver rio_driver = {
.owner = THIS_MODULE,
.name = "rio500",
.probe = probe_rio,
.disconnect = disconnect_rio,
.id_table = rio_table,
};
static int __init usb_rio_init(void)
{
int retval;
retval = usb_register(&rio_driver);
if (retval)
goto out;
info(DRIVER_VERSION ":" DRIVER_DESC);
out:
return retval;
}
static void __exit usb_rio_cleanup(void)
{
struct rio_usb_data *rio = &rio_instance;
rio->present = 0;
usb_deregister(&rio_driver);
}
module_init(usb_rio_init);
module_exit(usb_rio_cleanup);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");

查看文件

@@ -0,0 +1,37 @@
/* ----------------------------------------------------------------------
Copyright (C) 2000 Cesar Miquel (miquel@df.uba.ar)
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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
---------------------------------------------------------------------- */
#define RIO_SEND_COMMAND 0x1
#define RIO_RECV_COMMAND 0x2
#define RIO_DIR_OUT 0x0
#define RIO_DIR_IN 0x1
struct RioCommand {
short length;
int request;
int requesttype;
int value;
int index;
void __user *buffer;
int timeout;
};

查看文件

@@ -0,0 +1,14 @@
config USB_SISUSBVGA
tristate "USB 2.0 SVGA dongle support (Net2280/SiS315)"
depends on USB && USB_EHCI_HCD
---help---
Say Y here if you intend to attach a USB2VGA dongle based on a
Net2280 and a SiS315 chip.
Note that this device requires a USB 2.0 host controller. It will not
work with USB 1.x controllers.
To compile this driver as a module, choose M here: the module will be
called sisusb. If unsure, say N.

查看文件

@@ -0,0 +1,6 @@
#
# Makefile for the sisusb driver (if driver is inside kernel tree).
#
obj-$(CONFIG_USB_SISUSBVGA) += sisusb.o

文件差異過大導致無法顯示 Load Diff

查看文件

@@ -0,0 +1,278 @@
/*
* sisusb - usb kernel driver for Net2280/SiS315 based USB2VGA dongles
*
* Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, this code is licensed under the
* terms of the GPL v2.
*
* Otherwise, the following license terms apply:
*
* * Redistribution and use in source and binary forms, with or without
* * modification, are permitted provided that the following conditions
* * are met:
* * 1) Redistributions of source code must retain the above copyright
* * notice, this list of conditions and the following disclaimer.
* * 2) Redistributions in binary form must reproduce the above copyright
* * notice, this list of conditions and the following disclaimer in the
* * documentation and/or other materials provided with the distribution.
* * 3) The name of the author may not be used to endorse or promote products
* * derived from this software without specific prior written permission.
* *
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
* * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Author: Thomas Winischhofer <thomas@winischhofer.net>
*
*/
#ifndef _SISUSB_H_
#define _SISUSB_H_
#ifdef CONFIG_COMPAT
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10)
#include <linux/ioctl32.h>
#define SISUSB_OLD_CONFIG_COMPAT
#else
#define SISUSB_NEW_CONFIG_COMPAT
#endif
#endif
/* Version Information */
#define SISUSB_VERSION 0
#define SISUSB_REVISION 0
#define SISUSB_PATCHLEVEL 7
/* USB related */
#define SISUSB_MINOR 133 /* FIXME */
/* Size of the sisusb input/output buffers */
#define SISUSB_IBUF_SIZE 0x01000
#define SISUSB_OBUF_SIZE 0x10000 /* fixed */
#define NUMOBUFS 8 /* max number of output buffers/output URBs */
/* About endianness:
*
* 1) I/O ports, PCI config registers. The read/write()
* calls emulate inX/outX. Hence, the data is
* expected/delivered in machine endiannes by this
* driver.
* 2) Video memory. The data is copied 1:1. There is
* no swapping. Ever. This means for userland that
* the data has to be prepared properly. (Hint:
* think graphics data format, command queue,
* hardware cursor.)
* 3) MMIO. Data is copied 1:1. MMIO must be swapped
* properly by userland.
*
*/
#ifdef __BIG_ENDIAN
#define SISUSB_CORRECT_ENDIANNESS_PACKET(p) \
do { \
p->header = cpu_to_le16(p->header); \
p->address = cpu_to_le32(p->address); \
p->data = cpu_to_le32(p->data); \
} while(0)
#else
#define SISUSB_CORRECT_ENDIANNESS_PACKET(p)
#endif
struct sisusb_usb_data;
struct sisusb_urb_context { /* urb->context for outbound bulk URBs */
struct sisusb_usb_data *sisusb;
int urbindex;
int *actual_length;
};
struct sisusb_usb_data {
struct usb_device *sisusb_dev;
struct usb_interface *interface;
struct kref kref;
wait_queue_head_t wait_q; /* for syncind and timeouts */
struct semaphore lock; /* general race avoidance */
unsigned int ifnum; /* interface number of the USB device */
int minor; /* minor (for logging clarity) */
int isopen; /* !=0 if open */
int present; /* !=0 if device is present on the bus */
int ready; /* !=0 if device is ready for userland */
#ifdef SISUSB_OLD_CONFIG_COMPAT
int ioctl32registered;
#endif
int numobufs; /* number of obufs = number of out urbs */
char *obuf[NUMOBUFS], *ibuf; /* transfer buffers */
int obufsize, ibufsize;
dma_addr_t transfer_dma_out[NUMOBUFS];
dma_addr_t transfer_dma_in;
struct urb *sisurbout[NUMOBUFS];
struct urb *sisurbin;
unsigned char urbstatus[NUMOBUFS];
unsigned char completein;
struct sisusb_urb_context urbout_context[NUMOBUFS];
unsigned long flagb0;
unsigned long vrambase; /* framebuffer base */
unsigned int vramsize; /* framebuffer size (bytes) */
unsigned long mmiobase;
unsigned int mmiosize;
unsigned long ioportbase;
unsigned char devinit; /* device initialized? */
unsigned char gfxinit; /* graphics core initialized? */
unsigned short chipid, chipvendor;
unsigned short chiprevision;
};
#define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref)
/* USB transport related */
/* urbstatus */
#define SU_URB_BUSY 1
#define SU_URB_ALLOC 2
/* Endpoints */
#define SISUSB_EP_GFX_IN 0x0e /* gfx std packet out(0e)/in(8e) */
#define SISUSB_EP_GFX_OUT 0x0e
#define SISUSB_EP_GFX_BULK_OUT 0x01 /* gfx mem bulk out/in */
#define SISUSB_EP_GFX_BULK_IN 0x02 /* ? 2 is "OUT" ? */
#define SISUSB_EP_GFX_LBULK_OUT 0x03 /* gfx large mem bulk out */
#define SISUSB_EP_UNKNOWN_04 0x04 /* ? 4 is "OUT" ? - unused */
#define SISUSB_EP_BRIDGE_IN 0x0d /* Net2280 out(0d)/in(8d) */
#define SISUSB_EP_BRIDGE_OUT 0x0d
#define SISUSB_TYPE_MEM 0
#define SISUSB_TYPE_IO 1
struct sisusb_packet {
unsigned short header;
u32 address;
u32 data;
} __attribute__((__packed__));
#define CLEARPACKET(packet) memset(packet, 0, 10)
/* PCI bridge related */
#define SISUSB_PCI_MEMBASE 0xd0000000
#define SISUSB_PCI_MMIOBASE 0xe4000000
#define SISUSB_PCI_IOPORTBASE 0x0000d000
#define SISUSB_PCI_PSEUDO_MEMBASE 0x10000000
#define SISUSB_PCI_PSEUDO_MMIOBASE 0x20000000
#define SISUSB_PCI_PSEUDO_IOPORTBASE 0x0000d000
#define SISUSB_PCI_PSEUDO_PCIBASE 0x00010000
#define SISUSB_PCI_MMIOSIZE (128*1024)
#define SISUSB_PCI_PCONFSIZE 0x5c
/* graphics core related */
#define AROFFSET 0x40
#define ARROFFSET 0x41
#define GROFFSET 0x4e
#define SROFFSET 0x44
#define CROFFSET 0x54
#define MISCROFFSET 0x4c
#define MISCWOFFSET 0x42
#define INPUTSTATOFFSET 0x5A
#define PART1OFFSET 0x04
#define PART2OFFSET 0x10
#define PART3OFFSET 0x12
#define PART4OFFSET 0x14
#define PART5OFFSET 0x16
#define CAPTUREOFFSET 0x00
#define VIDEOOFFSET 0x02
#define COLREGOFFSET 0x48
#define PELMASKOFFSET 0x46
#define VGAENABLE 0x43
#define SISAR SISUSB_PCI_IOPORTBASE + AROFFSET
#define SISARR SISUSB_PCI_IOPORTBASE + ARROFFSET
#define SISGR SISUSB_PCI_IOPORTBASE + GROFFSET
#define SISSR SISUSB_PCI_IOPORTBASE + SROFFSET
#define SISCR SISUSB_PCI_IOPORTBASE + CROFFSET
#define SISMISCR SISUSB_PCI_IOPORTBASE + MISCROFFSET
#define SISMISCW SISUSB_PCI_IOPORTBASE + MISCWOFFSET
#define SISINPSTAT SISUSB_PCI_IOPORTBASE + INPUTSTATOFFSET
#define SISPART1 SISUSB_PCI_IOPORTBASE + PART1OFFSET
#define SISPART2 SISUSB_PCI_IOPORTBASE + PART2OFFSET
#define SISPART3 SISUSB_PCI_IOPORTBASE + PART3OFFSET
#define SISPART4 SISUSB_PCI_IOPORTBASE + PART4OFFSET
#define SISPART5 SISUSB_PCI_IOPORTBASE + PART5OFFSET
#define SISCAP SISUSB_PCI_IOPORTBASE + CAPTUREOFFSET
#define SISVID SISUSB_PCI_IOPORTBASE + VIDEOOFFSET
#define SISCOLIDXR SISUSB_PCI_IOPORTBASE + COLREGOFFSET - 1
#define SISCOLIDX SISUSB_PCI_IOPORTBASE + COLREGOFFSET
#define SISCOLDATA SISUSB_PCI_IOPORTBASE + COLREGOFFSET + 1
#define SISCOL2IDX SISPART5
#define SISCOL2DATA SISPART5 + 1
#define SISPEL SISUSB_PCI_IOPORTBASE + PELMASKOFFSET
#define SISVGAEN SISUSB_PCI_IOPORTBASE + VGAENABLE
#define SISDACA SISCOLIDX
#define SISDACD SISCOLDATA
/* ioctl related */
/* Structure argument for SISUSB_GET_INFO ioctl */
struct sisusb_info {
__u32 sisusb_id; /* for identifying sisusb */
#define SISUSB_ID 0x53495355 /* Identify myself with 'SISU' */
__u8 sisusb_version;
__u8 sisusb_revision;
__u8 sisusb_patchlevel;
__u8 sisusb_gfxinit; /* graphics core initialized? */
__u32 sisusb_vrambase;
__u32 sisusb_mmiobase;
__u32 sisusb_iobase;
__u32 sisusb_pcibase;
__u32 sisusb_vramsize; /* framebuffer size in bytes */
__u32 sisusb_minor;
__u32 sisusb_fbdevactive; /* != 0 if framebuffer device active */
__u8 sisusb_reserved[32]; /* for future use */
};
struct sisusb_command {
__u8 operation; /* see below */
__u8 data0; /* operation dependent */
__u8 data1; /* operation dependent */
__u8 data2; /* operation dependent */
__u32 data3; /* operation dependent */
__u32 data4; /* for future use */
};
#define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */
#define SUCMD_SET 0x02 /* data1 = value */
#define SUCMD_SETOR 0x03 /* data1 = or */
#define SUCMD_SETAND 0x04 /* data1 = and */
#define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */
#define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */
#define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */
#define SISUSB_COMMAND _IOWR(0xF3,0x3D,struct sisusb_command)
#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32)
#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info)
#endif /* SISUSB_H */

404
drivers/usb/misc/usblcd.c Normal file
查看文件

@@ -0,0 +1,404 @@
/*****************************************************************************
* USBLCD Kernel Driver *
* Version 1.05 *
* (C) 2005 Georges Toth <g.toth@e-biz.lu> *
* *
* This file is licensed under the GPL. See COPYING in the package. *
* Based on usb-skeleton.c 2.0 by Greg Kroah-Hartman (greg@kroah.com) *
* *
* *
* 28.02.05 Complete rewrite of the original usblcd.c driver, *
* based on usb_skeleton.c. *
* This new driver allows more than one USB-LCD to be connected *
* and controlled, at once *
*****************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
#define DRIVER_VERSION "USBLCD Driver Version 1.05"
#define USBLCD_MINOR 144
#define IOCTL_GET_HARD_VERSION 1
#define IOCTL_GET_DRV_VERSION 2
static struct usb_device_id id_table [] = {
{ .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, },
{ },
};
MODULE_DEVICE_TABLE (usb, id_table);
struct usb_lcd {
struct usb_device * udev; /* init: probe_lcd */
struct usb_interface * interface; /* the interface for this device */
unsigned char * bulk_in_buffer; /* the buffer to receive data */
size_t bulk_in_size; /* the size of the receive buffer */
__u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
__u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
struct kref kref;
};
#define to_lcd_dev(d) container_of(d, struct usb_lcd, kref)
static struct usb_driver lcd_driver;
static void lcd_delete(struct kref *kref)
{
struct usb_lcd *dev = to_lcd_dev(kref);
usb_put_dev(dev->udev);
kfree (dev->bulk_in_buffer);
kfree (dev);
}
static int lcd_open(struct inode *inode, struct file *file)
{
struct usb_lcd *dev;
struct usb_interface *interface;
int subminor;
int retval = 0;
subminor = iminor(inode);
interface = usb_find_interface(&lcd_driver, subminor);
if (!interface) {
err ("USBLCD: %s - error, can't find device for minor %d",
__FUNCTION__, subminor);
retval = -ENODEV;
goto exit;
}
dev = usb_get_intfdata(interface);
if (!dev) {
retval = -ENODEV;
goto exit;
}
/* increment our usage count for the device */
kref_get(&dev->kref);
/* save our object in the file's private structure */
file->private_data = dev;
exit:
return retval;
}
static int lcd_release(struct inode *inode, struct file *file)
{
struct usb_lcd *dev;
dev = (struct usb_lcd *)file->private_data;
if (dev == NULL)
return -ENODEV;
/* decrement the count on our device */
kref_put(&dev->kref, lcd_delete);
return 0;
}
static ssize_t lcd_read(struct file *file, char __user * buffer, size_t count, loff_t *ppos)
{
struct usb_lcd *dev;
int retval = 0;
int bytes_read;
dev = (struct usb_lcd *)file->private_data;
/* do a blocking bulk read to get data from the device */
retval = usb_bulk_msg(dev->udev,
usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
dev->bulk_in_buffer,
min(dev->bulk_in_size, count),
&bytes_read, 10000);
/* if the read was successful, copy the data to userspace */
if (!retval) {
if (copy_to_user(buffer, dev->bulk_in_buffer, bytes_read))
retval = -EFAULT;
else
retval = bytes_read;
}
return retval;
}
static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
struct usb_lcd *dev;
u16 bcdDevice;
char buf[30];
dev = (struct usb_lcd *)file->private_data;
if (dev == NULL)
return -ENODEV;
switch (cmd) {
case IOCTL_GET_HARD_VERSION:
bcdDevice = le16_to_cpu((dev->udev)->descriptor.bcdDevice);
sprintf(buf,"%1d%1d.%1d%1d",
(bcdDevice & 0xF000)>>12,
(bcdDevice & 0xF00)>>8,
(bcdDevice & 0xF0)>>4,
(bcdDevice & 0xF));
if (copy_to_user((void __user *)arg,buf,strlen(buf))!=0)
return -EFAULT;
break;
case IOCTL_GET_DRV_VERSION:
sprintf(buf,DRIVER_VERSION);
if (copy_to_user((void __user *)arg,buf,strlen(buf))!=0)
return -EFAULT;
break;
default:
return -ENOTTY;
break;
}
return 0;
}
static void lcd_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
{
struct usb_lcd *dev;
dev = (struct usb_lcd *)urb->context;
/* sync/async unlink faults aren't errors */
if (urb->status &&
!(urb->status == -ENOENT ||
urb->status == -ECONNRESET ||
urb->status == -ESHUTDOWN)) {
dbg("USBLCD: %s - nonzero write bulk status received: %d",
__FUNCTION__, urb->status);
}
/* free up our allocated buffer */
usb_buffer_free(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
}
static ssize_t lcd_write(struct file *file, const char __user * user_buffer, size_t count, loff_t *ppos)
{
struct usb_lcd *dev;
int retval = 0;
struct urb *urb = NULL;
char *buf = NULL;
dev = (struct usb_lcd *)file->private_data;
/* verify that we actually have some data to write */
if (count == 0)
goto exit;
/* create a urb, and a buffer for it, and copy the data to the urb */
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
retval = -ENOMEM;
goto error;
}
buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
if (!buf) {
retval = -ENOMEM;
goto error;
}
if (copy_from_user(buf, user_buffer, count)) {
retval = -EFAULT;
goto error;
}
/* initialize the urb properly */
usb_fill_bulk_urb(urb, dev->udev,
usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
buf, count, lcd_write_bulk_callback, dev);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
/* send the data out the bulk port */
retval = usb_submit_urb(urb, GFP_KERNEL);
if (retval) {
err("USBLCD: %s - failed submitting write urb, error %d", __FUNCTION__, retval);
goto error;
}
/* release our reference to this urb, the USB core will eventually free it entirely */
usb_free_urb(urb);
exit:
return count;
error:
usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
usb_free_urb(urb);
return retval;
}
static struct file_operations lcd_fops = {
.owner = THIS_MODULE,
.read = lcd_read,
.write = lcd_write,
.open = lcd_open,
.ioctl = lcd_ioctl,
.release = lcd_release,
};
/*
* * usb class driver info in order to get a minor number from the usb core,
* * and to have the device registered with devfs and the driver core
* */
static struct usb_class_driver lcd_class = {
.name = "usb/lcd%d",
.fops = &lcd_fops,
.mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
.minor_base = USBLCD_MINOR,
};
static int lcd_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
struct usb_lcd *dev = NULL;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
size_t buffer_size;
int i;
int retval = -ENOMEM;
/* allocate memory for our device state and initialize it */
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
err("Out of memory");
goto error;
}
memset(dev, 0x00, sizeof(*dev));
kref_init(&dev->kref);
dev->udev = usb_get_dev(interface_to_usbdev(interface));
dev->interface = interface;
if (le16_to_cpu(dev->udev->descriptor.idProduct) != 0x0001) {
warn(KERN_INFO "USBLCD model not supported.");
return -ENODEV;
}
/* set up the endpoint information */
/* use only the first bulk-in and bulk-out endpoints */
iface_desc = interface->cur_altsetting;
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
if (!dev->bulk_in_endpointAddr &&
(endpoint->bEndpointAddress & USB_DIR_IN) &&
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
== USB_ENDPOINT_XFER_BULK)) {
/* we found a bulk in endpoint */
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
dev->bulk_in_size = buffer_size;
dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!dev->bulk_in_buffer) {
err("Could not allocate bulk_in_buffer");
goto error;
}
}
if (!dev->bulk_out_endpointAddr &&
!(endpoint->bEndpointAddress & USB_DIR_IN) &&
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
== USB_ENDPOINT_XFER_BULK)) {
/* we found a bulk out endpoint */
dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
}
}
if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
err("Could not find both bulk-in and bulk-out endpoints");
goto error;
}
/* save our data pointer in this interface device */
usb_set_intfdata(interface, dev);
/* we can register the device now, as it is ready */
retval = usb_register_dev(interface, &lcd_class);
if (retval) {
/* something prevented us from registering this driver */
err("Not able to get a minor for this device.");
usb_set_intfdata(interface, NULL);
goto error;
}
i = le16_to_cpu(dev->udev->descriptor.bcdDevice);
info("USBLCD Version %1d%1d.%1d%1d found at address %d",
(i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF),
dev->udev->devnum);
/* let the user know what node this device is now attached to */
info("USB LCD device now attached to USBLCD-%d", interface->minor);
return 0;
error:
if (dev)
kref_put(&dev->kref, lcd_delete);
return retval;
}
static void lcd_disconnect(struct usb_interface *interface)
{
struct usb_lcd *dev;
int minor = interface->minor;
/* prevent skel_open() from racing skel_disconnect() */
lock_kernel();
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
/* give back our minor */
usb_deregister_dev(interface, &lcd_class);
unlock_kernel();
/* decrement our usage count */
kref_put(&dev->kref, lcd_delete);
info("USB LCD #%d now disconnected", minor);
}
static struct usb_driver lcd_driver = {
.owner = THIS_MODULE,
.name = "usblcd",
.probe = lcd_probe,
.disconnect = lcd_disconnect,
.id_table = id_table,
};
static int __init usb_lcd_init(void)
{
int result;
result = usb_register(&lcd_driver);
if (result)
err("usb_register failed. Error number %d", result);
return result;
}
static void __exit usb_lcd_exit(void)
{
usb_deregister(&lcd_driver);
}
module_init(usb_lcd_init);
module_exit(usb_lcd_exit);
MODULE_AUTHOR("Georges Toth <g.toth@e-biz.lu>");
MODULE_DESCRIPTION(DRIVER_VERSION);
MODULE_LICENSE("GPL");

181
drivers/usb/misc/usbled.c Normal file
查看文件

@@ -0,0 +1,181 @@
/*
* USB LED driver - 1.1
*
* Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com)
*
* 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, version 2.
*
*/
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/usb.h>
#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com"
#define DRIVER_DESC "USB LED Driver"
#define VENDOR_ID 0x0fc5
#define PRODUCT_ID 0x1223
/* table of devices that work with this driver */
static struct usb_device_id id_table [] = {
{ USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
{ },
};
MODULE_DEVICE_TABLE (usb, id_table);
struct usb_led {
struct usb_device * udev;
unsigned char blue;
unsigned char red;
unsigned char green;
};
#define BLUE 0x04
#define RED 0x02
#define GREEN 0x01
static void change_color(struct usb_led *led)
{
int retval;
unsigned char color = 0x07;
unsigned char *buffer;
buffer = kmalloc(8, GFP_KERNEL);
if (!buffer) {
dev_err(&led->udev->dev, "out of memory\n");
return;
}
if (led->blue)
color &= ~(BLUE);
if (led->red)
color &= ~(RED);
if (led->green)
color &= ~(GREEN);
dev_dbg(&led->udev->dev,
"blue = %d, red = %d, green = %d, color = %.2x\n",
led->blue, led->red, led->green, color);
retval = usb_control_msg(led->udev,
usb_sndctrlpipe(led->udev, 0),
0x12,
0xc8,
(0x02 * 0x100) + 0x0a,
(0x00 * 0x100) + color,
buffer,
8,
2000);
if (retval)
dev_dbg(&led->udev->dev, "retval = %d\n", retval);
kfree(buffer);
}
#define show_set(value) \
static ssize_t show_##value(struct device *dev, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct usb_led *led = usb_get_intfdata(intf); \
\
return sprintf(buf, "%d\n", led->value); \
} \
static ssize_t set_##value(struct device *dev, const char *buf, size_t count) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct usb_led *led = usb_get_intfdata(intf); \
int temp = simple_strtoul(buf, NULL, 10); \
\
led->value = temp; \
change_color(led); \
return count; \
} \
static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
show_set(blue);
show_set(red);
show_set(green);
static int led_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(interface);
struct usb_led *dev = NULL;
int retval = -ENOMEM;
dev = kmalloc(sizeof(struct usb_led), GFP_KERNEL);
if (dev == NULL) {
dev_err(&interface->dev, "Out of memory\n");
goto error;
}
memset (dev, 0x00, sizeof (*dev));
dev->udev = usb_get_dev(udev);
usb_set_intfdata (interface, dev);
device_create_file(&interface->dev, &dev_attr_blue);
device_create_file(&interface->dev, &dev_attr_red);
device_create_file(&interface->dev, &dev_attr_green);
dev_info(&interface->dev, "USB LED device now attached\n");
return 0;
error:
kfree(dev);
return retval;
}
static void led_disconnect(struct usb_interface *interface)
{
struct usb_led *dev;
dev = usb_get_intfdata (interface);
usb_set_intfdata (interface, NULL);
device_remove_file(&interface->dev, &dev_attr_blue);
device_remove_file(&interface->dev, &dev_attr_red);
device_remove_file(&interface->dev, &dev_attr_green);
usb_put_dev(dev->udev);
kfree(dev);
dev_info(&interface->dev, "USB LED now disconnected\n");
}
static struct usb_driver led_driver = {
.owner = THIS_MODULE,
.name = "usbled",
.probe = led_probe,
.disconnect = led_disconnect,
.id_table = id_table,
};
static int __init usb_led_init(void)
{
int retval = 0;
retval = usb_register(&led_driver);
if (retval)
err("usb_register failed. Error number %d", retval);
return retval;
}
static void __exit usb_led_exit(void)
{
usb_deregister(&led_driver);
}
module_init (usb_led_init);
module_exit (usb_led_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

2140
drivers/usb/misc/usbtest.c Normal file

文件差異過大導致無法顯示 Load Diff

674
drivers/usb/misc/uss720.c Normal file
查看文件

@@ -0,0 +1,674 @@
/*****************************************************************************/
/*
* uss720.c -- USS720 USB Parport Cable.
*
* Copyright (C) 1999
* Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Based on parport_pc.c
*
* History:
* 0.1 04.08.99 Created
* 0.2 07.08.99 Some fixes mainly suggested by Tim Waugh
* Interrupt handling currently disabled because
* usb_request_irq crashes somewhere within ohci.c
* for no apparent reason (that is for me, anyway)
* ECP currently untested
* 0.3 10.08.99 fixing merge errors
* 0.4 13.08.99 Added Vendor/Product ID of Brad Hard's cable
* 0.5 20.09.99 usb_control_msg wrapper used
* Nov01.00 usb_device_table support by Adam J. Richter
* 08.04.01 Identify version on module load. gb
*
*/
/*****************************************************************************/
#include <linux/module.h>
#include <linux/socket.h>
#include <linux/parport.h>
#include <linux/init.h>
#include <linux/usb.h>
#include <linux/delay.h>
/*
* Version Information
*/
#define DRIVER_VERSION "v0.5"
#define DRIVER_AUTHOR "Thomas M. Sailer, sailer@ife.ee.ethz.ch"
#define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip"
/* --------------------------------------------------------------------- */
struct parport_uss720_private {
struct usb_device *usbdev;
void *irqhandle;
unsigned int irqpipe;
unsigned char reg[7]; /* USB registers */
};
/* --------------------------------------------------------------------- */
static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val)
{
struct parport_uss720_private *priv = pp->private_data;
struct usb_device *usbdev = priv->usbdev;
static const unsigned char regindex[9] = {
4, 0, 1, 5, 5, 0, 2, 3, 6
};
int ret;
if (!usbdev)
return -1;
ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, 1000);
if (ret != 7) {
printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x expected 7\n",
(unsigned int)reg, ret);
ret = -1;
} else {
#if 0
printk(KERN_DEBUG "uss720: get_1284_register(%d) return %02x %02x %02x %02x %02x %02x %02x\n",
(unsigned int)reg, (unsigned int)priv->reg[0], (unsigned int)priv->reg[1],
(unsigned int)priv->reg[2], (unsigned int)priv->reg[3], (unsigned int)priv->reg[4],
(unsigned int)priv->reg[5], (unsigned int)priv->reg[6]);
#endif
/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
if (priv->reg[2] & priv->reg[1] & 0x10)
parport_generic_irq(0, pp, NULL);
ret = 0;
}
if (val)
*val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
return ret;
}
static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val)
{
struct parport_uss720_private *priv = pp->private_data;
struct usb_device *usbdev = priv->usbdev;
int ret;
if (!usbdev)
return -1;
ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, 1000);
if (ret) {
printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n",
(unsigned int)reg, (unsigned int)val, ret);
} else {
#if 0
printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x)\n",
(unsigned int)reg, (unsigned int)val);
#endif
}
return ret;
}
/* --------------------------------------------------------------------- */
/* ECR modes */
#define ECR_SPP 00
#define ECR_PS2 01
#define ECR_PPF 02
#define ECR_ECP 03
#define ECR_EPP 04
/* Safely change the mode bits in the ECR */
static int change_mode(struct parport *pp, int m)
{
struct parport_uss720_private *priv = pp->private_data;
int mode;
if (get_1284_register(pp, 6, NULL))
return -EIO;
/* Bits <7:5> contain the mode. */
mode = (priv->reg[2] >> 5) & 0x7;
if (mode == m)
return 0;
/* We have to go through mode 000 or 001 */
if (mode > ECR_PS2 && m > ECR_PS2)
if (change_mode(pp, ECR_PS2))
return -EIO;
if (m <= ECR_PS2 && !(priv->reg[1] & 0x20)) {
/* This mode resets the FIFO, so we may
* have to wait for it to drain first. */
unsigned long expire = jiffies + pp->physport->cad->timeout;
switch (mode) {
case ECR_PPF: /* Parallel Port FIFO mode */
case ECR_ECP: /* ECP Parallel Port mode */
/* Poll slowly. */
for (;;) {
if (get_1284_register(pp, 6, NULL))
return -EIO;
if (priv->reg[2] & 0x01)
break;
if (time_after_eq (jiffies, expire))
/* The FIFO is stuck. */
return -EBUSY;
msleep_interruptible(10);
if (signal_pending (current))
break;
}
}
}
/* Set the mode. */
if (set_1284_register(pp, 6, m << 5))
return -EIO;
return 0;
}
/*
* Clear TIMEOUT BIT in EPP MODE
*/
static int clear_epp_timeout(struct parport *pp)
{
unsigned char stat;
if (get_1284_register(pp, 1, &stat))
return 1;
return stat & 1;
}
/*
* Access functions.
*/
#if 0
static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
{
struct parport *pp = (struct parport *)dev_id;
struct parport_uss720_private *priv = pp->private_data;
if (usbstatus != 0 || len < 4 || !buffer)
return 1;
memcpy(priv->reg, buffer, 4);
/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
if (priv->reg[2] & priv->reg[1] & 0x10)
parport_generic_irq(0, pp, NULL);
return 1;
}
#endif
static void parport_uss720_write_data(struct parport *pp, unsigned char d)
{
set_1284_register(pp, 0, d);
}
static unsigned char parport_uss720_read_data(struct parport *pp)
{
unsigned char ret;
if (get_1284_register(pp, 0, &ret))
return 0;
return ret;
}
static void parport_uss720_write_control(struct parport *pp, unsigned char d)
{
struct parport_uss720_private *priv = pp->private_data;
d = (d & 0xf) | (priv->reg[1] & 0xf0);
if (set_1284_register(pp, 2, d))
return;
priv->reg[1] = d;
}
static unsigned char parport_uss720_read_control(struct parport *pp)
{
struct parport_uss720_private *priv = pp->private_data;
return priv->reg[1] & 0xf; /* Use soft copy */
}
static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned char mask, unsigned char val)
{
struct parport_uss720_private *priv = pp->private_data;
unsigned char d;
mask &= 0x0f;
val &= 0x0f;
d = (priv->reg[1] & (~mask)) ^ val;
if (set_1284_register(pp, 2, d))
return 0;
priv->reg[1] = d;
return d & 0xf;
}
static unsigned char parport_uss720_read_status(struct parport *pp)
{
unsigned char ret;
if (get_1284_register(pp, 1, &ret))
return 0;
return ret & 0xf8;
}
static void parport_uss720_disable_irq(struct parport *pp)
{
struct parport_uss720_private *priv = pp->private_data;
unsigned char d;
d = priv->reg[1] & ~0x10;
if (set_1284_register(pp, 2, d))
return;
priv->reg[1] = d;
}
static void parport_uss720_enable_irq(struct parport *pp)
{
struct parport_uss720_private *priv = pp->private_data;
unsigned char d;
d = priv->reg[1] | 0x10;
if (set_1284_register(pp, 2, d))
return;
priv->reg[1] = d;
}
static void parport_uss720_data_forward (struct parport *pp)
{
struct parport_uss720_private *priv = pp->private_data;
unsigned char d;
d = priv->reg[1] & ~0x20;
if (set_1284_register(pp, 2, d))
return;
priv->reg[1] = d;
}
static void parport_uss720_data_reverse (struct parport *pp)
{
struct parport_uss720_private *priv = pp->private_data;
unsigned char d;
d = priv->reg[1] | 0x20;
if (set_1284_register(pp, 2, d))
return;
priv->reg[1] = d;
}
static void parport_uss720_init_state(struct pardevice *dev, struct parport_state *s)
{
s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
s->u.pc.ecr = 0x24;
}
static void parport_uss720_save_state(struct parport *pp, struct parport_state *s)
{
struct parport_uss720_private *priv = pp->private_data;
if (get_1284_register(pp, 2, NULL))
return;
s->u.pc.ctr = priv->reg[1];
s->u.pc.ecr = priv->reg[2];
}
static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s)
{
set_1284_register(pp, 2, s->u.pc.ctr);
set_1284_register(pp, 6, s->u.pc.ecr);
get_1284_register(pp, 2, NULL);
}
static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags)
{
struct parport_uss720_private *priv = pp->private_data;
size_t got = 0;
if (change_mode(pp, ECR_EPP))
return 0;
for (; got < length; got++) {
if (get_1284_register(pp, 4, (char *)buf))
break;
buf++;
if (priv->reg[0] & 0x01) {
clear_epp_timeout(pp);
break;
}
}
change_mode(pp, ECR_PS2);
return got;
}
static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf, size_t length, int flags)
{
#if 0
struct parport_uss720_private *priv = pp->private_data;
size_t written = 0;
if (change_mode(pp, ECR_EPP))
return 0;
for (; written < length; written++) {
if (set_1284_register(pp, 4, (char *)buf))
break;
((char*)buf)++;
if (get_1284_register(pp, 1, NULL))
break;
if (priv->reg[0] & 0x01) {
clear_epp_timeout(pp);
break;
}
}
change_mode(pp, ECR_PS2);
return written;
#else
struct parport_uss720_private *priv = pp->private_data;
struct usb_device *usbdev = priv->usbdev;
int rlen;
int i;
if (!usbdev)
return 0;
if (change_mode(pp, ECR_EPP))
return 0;
i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buf, length, &rlen, 20000);
if (i)
printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buf, length, rlen);
change_mode(pp, ECR_PS2);
return rlen;
#endif
}
static size_t parport_uss720_epp_read_addr(struct parport *pp, void *buf, size_t length, int flags)
{
struct parport_uss720_private *priv = pp->private_data;
size_t got = 0;
if (change_mode(pp, ECR_EPP))
return 0;
for (; got < length; got++) {
if (get_1284_register(pp, 3, (char *)buf))
break;
buf++;
if (priv->reg[0] & 0x01) {
clear_epp_timeout(pp);
break;
}
}
change_mode(pp, ECR_PS2);
return got;
}
static size_t parport_uss720_epp_write_addr(struct parport *pp, const void *buf, size_t length, int flags)
{
struct parport_uss720_private *priv = pp->private_data;
size_t written = 0;
if (change_mode(pp, ECR_EPP))
return 0;
for (; written < length; written++) {
if (set_1284_register(pp, 3, *(char *)buf))
break;
buf++;
if (get_1284_register(pp, 1, NULL))
break;
if (priv->reg[0] & 0x01) {
clear_epp_timeout(pp);
break;
}
}
change_mode(pp, ECR_PS2);
return written;
}
static size_t parport_uss720_ecp_write_data(struct parport *pp, const void *buffer, size_t len, int flags)
{
struct parport_uss720_private *priv = pp->private_data;
struct usb_device *usbdev = priv->usbdev;
int rlen;
int i;
if (!usbdev)
return 0;
if (change_mode(pp, ECR_ECP))
return 0;
i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, 20000);
if (i)
printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buffer, len, rlen);
change_mode(pp, ECR_PS2);
return rlen;
}
static size_t parport_uss720_ecp_read_data(struct parport *pp, void *buffer, size_t len, int flags)
{
struct parport_uss720_private *priv = pp->private_data;
struct usb_device *usbdev = priv->usbdev;
int rlen;
int i;
if (!usbdev)
return 0;
if (change_mode(pp, ECR_ECP))
return 0;
i = usb_bulk_msg(usbdev, usb_rcvbulkpipe(usbdev, 2), buffer, len, &rlen, 20000);
if (i)
printk(KERN_ERR "uss720: recvbulk ep 2 buf %p len %Zu rlen %u\n", buffer, len, rlen);
change_mode(pp, ECR_PS2);
return rlen;
}
static size_t parport_uss720_ecp_write_addr(struct parport *pp, const void *buffer, size_t len, int flags)
{
size_t written = 0;
if (change_mode(pp, ECR_ECP))
return 0;
for (; written < len; written++) {
if (set_1284_register(pp, 5, *(char *)buffer))
break;
buffer++;
}
change_mode(pp, ECR_PS2);
return written;
}
static size_t parport_uss720_write_compat(struct parport *pp, const void *buffer, size_t len, int flags)
{
struct parport_uss720_private *priv = pp->private_data;
struct usb_device *usbdev = priv->usbdev;
int rlen;
int i;
if (!usbdev)
return 0;
if (change_mode(pp, ECR_PPF))
return 0;
i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, 20000);
if (i)
printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buffer, len, rlen);
change_mode(pp, ECR_PS2);
return rlen;
}
/* --------------------------------------------------------------------- */
static struct parport_operations parport_uss720_ops =
{
.owner = THIS_MODULE,
.write_data = parport_uss720_write_data,
.read_data = parport_uss720_read_data,
.write_control = parport_uss720_write_control,
.read_control = parport_uss720_read_control,
.frob_control = parport_uss720_frob_control,
.read_status = parport_uss720_read_status,
.enable_irq = parport_uss720_enable_irq,
.disable_irq = parport_uss720_disable_irq,
.data_forward = parport_uss720_data_forward,
.data_reverse = parport_uss720_data_reverse,
.init_state = parport_uss720_init_state,
.save_state = parport_uss720_save_state,
.restore_state = parport_uss720_restore_state,
.epp_write_data = parport_uss720_epp_write_data,
.epp_read_data = parport_uss720_epp_read_data,
.epp_write_addr = parport_uss720_epp_write_addr,
.epp_read_addr = parport_uss720_epp_read_addr,
.ecp_write_data = parport_uss720_ecp_write_data,
.ecp_read_data = parport_uss720_ecp_read_data,
.ecp_write_addr = parport_uss720_ecp_write_addr,
.compat_write_data = parport_uss720_write_compat,
.nibble_read_data = parport_ieee1284_read_nibble,
.byte_read_data = parport_ieee1284_read_byte,
};
/* --------------------------------------------------------------------- */
static int uss720_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *usbdev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_host_endpoint *endpoint;
struct parport_uss720_private *priv;
struct parport *pp;
int i;
printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n",
le16_to_cpu(usbdev->descriptor.idVendor),
le16_to_cpu(usbdev->descriptor.idProduct));
/* our known interfaces have 3 alternate settings */
if (intf->num_altsetting != 3)
return -ENODEV;
i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2);
printk(KERN_DEBUG "uss720: set inteface result %d\n", i);
interface = intf->cur_altsetting;
/*
* Allocate parport interface
*/
printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");
if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL)))
return -ENOMEM;
if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) {
printk(KERN_WARNING "usb-uss720: could not register parport\n");
goto probe_abort;
}
pp->private_data = priv;
priv->usbdev = usbdev;
pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;
/* set the USS720 control register to manual mode, no ECP compression, enable all ints */
set_1284_register(pp, 7, 0x00);
set_1284_register(pp, 6, 0x30); /* PS/2 mode */
set_1284_register(pp, 2, 0x0c);
/* debugging */
get_1284_register(pp, 0, NULL);
printk("uss720: reg: %02x %02x %02x %02x %02x %02x %02x\n",
priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
endpoint = &interface->endpoint[2];
printk(KERN_DEBUG "uss720: epaddr %d interval %d\n", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);
#if 0
priv->irqpipe = usb_rcvctrlpipe(usbdev, endpoint->bEndpointAddress);
i = usb_request_irq(usbdev, priv->irqpipe,
uss720_irq, endpoint->bInterval,
pp, &priv->irqhandle);
if (i) {
printk (KERN_WARNING "usb-uss720: usb_request_irq failed (0x%x)\n", i);
goto probe_abort_port;
}
#endif
parport_announce_port(pp);
usb_set_intfdata (intf, pp);
return 0;
#if 0
probe_abort_port:
parport_put_port(pp);
#endif
probe_abort:
kfree(priv);
return -ENODEV;
}
static void uss720_disconnect(struct usb_interface *intf)
{
struct parport *pp = usb_get_intfdata (intf);
struct parport_uss720_private *priv;
usb_set_intfdata (intf, NULL);
if (pp) {
priv = pp->private_data;
parport_remove_port(pp);
#if 0
usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
#endif
priv->usbdev = NULL;
parport_put_port(pp);
kfree(priv);
}
}
/* table of cables that work through this driver */
static struct usb_device_id uss720_table [] = {
{ USB_DEVICE(0x047e, 0x1001) },
{ USB_DEVICE(0x0557, 0x2001) },
{ USB_DEVICE(0x0729, 0x1284) },
{ USB_DEVICE(0x1293, 0x0002) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, uss720_table);
static struct usb_driver uss720_driver = {
.owner = THIS_MODULE,
.name = "uss720",
.probe = uss720_probe,
.disconnect = uss720_disconnect,
.id_table = uss720_table,
};
/* --------------------------------------------------------------------- */
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
static int __init uss720_init(void)
{
int retval;
retval = usb_register(&uss720_driver);
if (retval)
goto out;
info(DRIVER_VERSION ":" DRIVER_DESC);
out:
return retval;
}
static void __exit uss720_cleanup(void)
{
usb_deregister(&uss720_driver);
}
module_init(uss720_init);
module_exit(uss720_cleanup);
/* --------------------------------------------------------------------- */