1
0
Fork 0

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (229 commits)
  USB: remove unused usb_buffer_alloc and usb_buffer_free macros
  usb: musb: update gfp/slab.h includes
  USB: ftdi_sio: fix legacy SIO-device header
  USB: kl5usb105: reimplement using generic framework
  USB: kl5usb105: minor clean ups
  USB: kl5usb105: fix memory leak
  USB: io_ti: use kfifo to implement write buffering
  USB: io_ti: remove unsused private counter
  USB: ti_usb: use kfifo to implement write buffering
  USB: ir-usb: fix incorrect write-buffer length
  USB: aircable: fix incorrect write-buffer length
  USB: safe_serial: straighten out read processing
  USB: safe_serial: reimplement read using generic framework
  USB: safe_serial: reimplement write using generic framework
  usb-storage: always print quirks
  USB: usb-storage: trivial debug improvements
  USB: oti6858: use port write fifo
  USB: oti6858: use kfifo to implement write buffering
  USB: cypress_m8: use kfifo to implement write buffering
  USB: cypress_m8: remove unused drain define
  ...

Fix up conflicts (due to usb_buffer_alloc/free renaming) in
	drivers/input/tablet/acecad.c
	drivers/input/tablet/kbtab.c
	drivers/input/tablet/wacom_sys.c
	drivers/media/video/gspca/gspca.c
	sound/usb/usbaudio.c
hifive-unleashed-5.1
Linus Torvalds 2010-05-20 21:26:12 -07:00
commit 7a9b149212
261 changed files with 17253 additions and 8371 deletions

View File

@ -0,0 +1,31 @@
What: /sys/bus/usb/devices/.../power/level
Date: March 2007
KernelVersion: 2.6.21
Contact: Alan Stern <stern@rowland.harvard.edu>
Description:
Each USB device directory will contain a file named
power/level. This file holds a power-level setting for
the device, either "on" or "auto".
"on" means that the device is not allowed to autosuspend,
although normal suspends for system sleep will still
be honored. "auto" means the device will autosuspend
and autoresume in the usual manner, according to the
capabilities of its driver.
During normal use, devices should be left in the "auto"
level. The "on" level is meant for administrative uses.
If you want to suspend a device immediately but leave it
free to wake up in response to I/O requests, you should
write "0" to power/autosuspend.
Device not capable of proper suspend and resume should be
left in the "on" level. Although the USB spec requires
devices to support suspend/resume, many of them do not.
In fact so many don't that by default, the USB core
initializes all non-hub devices in the "on" level. Some
drivers may change this setting when they are bound.
This file is deprecated and will be removed after 2010.
Use the power/control file instead; it does exactly the
same thing.

View File

@ -14,34 +14,6 @@ Description:
The autosuspend delay for newly-created devices is set to
the value of the usbcore.autosuspend module parameter.
What: /sys/bus/usb/devices/.../power/level
Date: March 2007
KernelVersion: 2.6.21
Contact: Alan Stern <stern@rowland.harvard.edu>
Description:
Each USB device directory will contain a file named
power/level. This file holds a power-level setting for
the device, either "on" or "auto".
"on" means that the device is not allowed to autosuspend,
although normal suspends for system sleep will still
be honored. "auto" means the device will autosuspend
and autoresume in the usual manner, according to the
capabilities of its driver.
During normal use, devices should be left in the "auto"
level. The "on" level is meant for administrative uses.
If you want to suspend a device immediately but leave it
free to wake up in response to I/O requests, you should
write "0" to power/autosuspend.
Device not capable of proper suspend and resume should be
left in the "on" level. Although the USB spec requires
devices to support suspend/resume, many of them do not.
In fact so many don't that by default, the USB core
initializes all non-hub devices in the "on" level. Some
drivers may change this setting when they are bound.
What: /sys/bus/usb/devices/.../power/persist
Date: May 2007
KernelVersion: 2.6.23

View File

@ -0,0 +1,9 @@
What: /sys/devices/platform/_UDC_/gadget/suspended
Date: April 2010
Contact: Fabien Chouteau <fabien.chouteau@barco.com>
Description:
Show the suspend state of an USB composite gadget.
1 -> suspended
0 -> resumed
(_UDC_ is the name of the USB Device Controller driver)

View File

@ -342,7 +342,7 @@ static inline void skel_delete (struct usb_skel *dev)
{
kfree (dev->bulk_in_buffer);
if (dev->bulk_out_buffer != NULL)
usb_buffer_free (dev->udev, dev->bulk_out_size,
usb_free_coherent (dev->udev, dev->bulk_out_size,
dev->bulk_out_buffer,
dev->write_urb->transfer_dma);
usb_free_urb (dev->write_urb);

View File

@ -0,0 +1,78 @@
Background
==========
Bulk endpoint streams were added in the USB 3.0 specification. Streams allow a
device driver to overload a bulk endpoint so that multiple transfers can be
queued at once.
Streams are defined in sections 4.4.6.4 and 8.12.1.4 of the Universal Serial Bus
3.0 specification at http://www.usb.org/developers/docs/ The USB Attached SCSI
Protocol, which uses streams to queue multiple SCSI commands, can be found on
the T10 website (http://t10.org/).
Device-side implications
========================
Once a buffer has been queued to a stream ring, the device is notified (through
an out-of-band mechanism on another endpoint) that data is ready for that stream
ID. The device then tells the host which "stream" it wants to start. The host
can also initiate a transfer on a stream without the device asking, but the
device can refuse that transfer. Devices can switch between streams at any
time.
Driver implications
===================
int usb_alloc_streams(struct usb_interface *interface,
struct usb_host_endpoint **eps, unsigned int num_eps,
unsigned int num_streams, gfp_t mem_flags);
Device drivers will call this API to request that the host controller driver
allocate memory so the driver can use up to num_streams stream IDs. They must
pass an array of usb_host_endpoints that need to be setup with similar stream
IDs. This is to ensure that a UASP driver will be able to use the same stream
ID for the bulk IN and OUT endpoints used in a Bi-directional command sequence.
The return value is an error condition (if one of the endpoints doesn't support
streams, or the xHCI driver ran out of memory), or the number of streams the
host controller allocated for this endpoint. The xHCI host controller hardware
declares how many stream IDs it can support, and each bulk endpoint on a
SuperSpeed device will say how many stream IDs it can handle. Therefore,
drivers should be able to deal with being allocated less stream IDs than they
requested.
Do NOT call this function if you have URBs enqueued for any of the endpoints
passed in as arguments. Do not call this function to request less than two
streams.
Drivers will only be allowed to call this API once for the same endpoint
without calling usb_free_streams(). This is a simplification for the xHCI host
controller driver, and may change in the future.
Picking new Stream IDs to use
============================
Stream ID 0 is reserved, and should not be used to communicate with devices. If
usb_alloc_streams() returns with a value of N, you may use streams 1 though N.
To queue an URB for a specific stream, set the urb->stream_id value. If the
endpoint does not support streams, an error will be returned.
Note that new API to choose the next stream ID will have to be added if the xHCI
driver supports secondary stream IDs.
Clean up
========
If a driver wishes to stop using streams to communicate with the device, it
should call
void usb_free_streams(struct usb_interface *interface,
struct usb_host_endpoint **eps, unsigned int num_eps,
gfp_t mem_flags);
All stream IDs will be deallocated when the driver releases the interface, to
ensure that drivers that don't support streams will be able to use the endpoint.

View File

@ -16,11 +16,11 @@ OR: they can now be DMA-aware.
manage dma mappings for existing dma-ready buffers (see below).
- URBs have an additional "transfer_dma" field, as well as a transfer_flags
bit saying if it's valid. (Control requests also have "setup_dma" and a
corresponding transfer_flags bit.)
bit saying if it's valid. (Control requests also have "setup_dma", but
drivers must not use it.)
- "usbcore" will map those DMA addresses, if a DMA-aware driver didn't do
it first and set URB_NO_TRANSFER_DMA_MAP or URB_NO_SETUP_DMA_MAP. HCDs
- "usbcore" will map this DMA address, if a DMA-aware driver didn't do
it first and set URB_NO_TRANSFER_DMA_MAP. HCDs
don't manage dma mappings for URBs.
- There's a new "generic DMA API", parts of which are usable by USB device
@ -43,22 +43,16 @@ and effects like cache-trashing can impose subtle penalties.
kind of addresses to store in urb->transfer_buffer and urb->transfer_dma.
You'd also set URB_NO_TRANSFER_DMA_MAP in urb->transfer_flags:
void *usb_buffer_alloc (struct usb_device *dev, size_t size,
void *usb_alloc_coherent (struct usb_device *dev, size_t size,
int mem_flags, dma_addr_t *dma);
void usb_buffer_free (struct usb_device *dev, size_t size,
void usb_free_coherent (struct usb_device *dev, size_t size,
void *addr, dma_addr_t dma);
Most drivers should *NOT* be using these primitives; they don't need
to use this type of memory ("dma-coherent"), and memory returned from
kmalloc() will work just fine.
For control transfers you can use the buffer primitives or not for each
of the transfer buffer and setup buffer independently. Set the flag bits
URB_NO_TRANSFER_DMA_MAP and URB_NO_SETUP_DMA_MAP to indicate which
buffers you have prepared. For non-control transfers URB_NO_SETUP_DMA_MAP
is ignored.
The memory buffer returned is "dma-coherent"; sometimes you might need to
force a consistent memory access ordering by using memory barriers. It's
not using a streaming DMA mapping, so it's good for small transfers on
@ -130,8 +124,8 @@ of Documentation/PCI/PCI-DMA-mapping.txt, titled "What memory is DMA-able?")
void usb_buffer_unmap (struct urb *urb);
The calls manage urb->transfer_dma for you, and set URB_NO_TRANSFER_DMA_MAP
so that usbcore won't map or unmap the buffer. The same goes for
urb->setup_dma and URB_NO_SETUP_DMA_MAP for control requests.
so that usbcore won't map or unmap the buffer. They cannot be used for
setup_packet buffers in control requests.
Note that several of those interfaces are currently commented out, since
they don't have current users. See the source code. Other than the dmasync

View File

@ -0,0 +1,445 @@
Linux USB HID gadget driver
Introduction
The HID Gadget driver provides emulation of USB Human Interface
Devices (HID). The basic HID handling is done in the kernel,
and HID reports can be sent/received through I/O on the
/dev/hidgX character devices.
For more details about HID, see the developer page on
http://www.usb.org/developers/hidpage/
Configuration
g_hid is a platform driver, so to use it you need to add
struct platform_device(s) to your platform code defining the
HID function descriptors you want to use - E.G. something
like:
#include <linux/platform_device.h>
#include <linux/usb/g_hid.h>
/* hid descriptor for a keyboard */
static struct hidg_func_descriptor my_hid_data = {
.subclass = 0, /* No subclass */
.protocol = 1, /* Keyboard */
.report_length = 8,
.report_desc_length = 63,
.report_desc = {
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
0x09, 0x06, /* USAGE (Keyboard) */
0xa1, 0x01, /* COLLECTION (Application) */
0x05, 0x07, /* USAGE_PAGE (Keyboard) */
0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */
0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
0x75, 0x01, /* REPORT_SIZE (1) */
0x95, 0x08, /* REPORT_COUNT (8) */
0x81, 0x02, /* INPUT (Data,Var,Abs) */
0x95, 0x01, /* REPORT_COUNT (1) */
0x75, 0x08, /* REPORT_SIZE (8) */
0x81, 0x03, /* INPUT (Cnst,Var,Abs) */
0x95, 0x05, /* REPORT_COUNT (5) */
0x75, 0x01, /* REPORT_SIZE (1) */
0x05, 0x08, /* USAGE_PAGE (LEDs) */
0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */
0x29, 0x05, /* USAGE_MAXIMUM (Kana) */
0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
0x95, 0x01, /* REPORT_COUNT (1) */
0x75, 0x03, /* REPORT_SIZE (3) */
0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */
0x95, 0x06, /* REPORT_COUNT (6) */
0x75, 0x08, /* REPORT_SIZE (8) */
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
0x25, 0x65, /* LOGICAL_MAXIMUM (101) */
0x05, 0x07, /* USAGE_PAGE (Keyboard) */
0x19, 0x00, /* USAGE_MINIMUM (Reserved) */
0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */
0x81, 0x00, /* INPUT (Data,Ary,Abs) */
0xc0 /* END_COLLECTION */
}
};
static struct platform_device my_hid = {
.name = "hidg",
.id = 0,
.num_resources = 0,
.resource = 0,
.dev.platform_data = &my_hid_data,
};
You can add as many HID functions as you want, only limited by
the amount of interrupt endpoints your gadget driver supports.
Send and receive HID reports
HID reports can be sent/received using read/write on the
/dev/hidgX character devices. See below for an example program
to do this.
hid_gadget_test is a small interactive program to test the HID
gadget driver. To use, point it at a hidg device and set the
device type (keyboard / mouse / joystick) - E.G.:
# hid_gadget_test /dev/hidg0 keyboard
You are now in the prompt of hid_gadget_test. You can type any
combination of options and values. Available options and
values are listed at program start. In keyboard mode you can
send up to six values.
For example type: g i s t r --left-shift
Hit return and the corresponding report will be sent by the
HID gadget.
Another interesting example is the caps lock test. Type
-caps-lock and hit return. A report is then sent by the
gadget and you should receive the host answer, corresponding
to the caps lock LED status.
--caps-lock
recv report:2
With this command:
# hid_gadget_test /dev/hidg1 mouse
You can test the mouse emulation. Values are two signed numbers.
Sample code
/* hid_gadget_test */
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUF_LEN 512
struct options {
const char *opt;
unsigned char val;
};
static struct options kmod[] = {
{.opt = "--left-ctrl", .val = 0x01},
{.opt = "--right-ctrl", .val = 0x10},
{.opt = "--left-shift", .val = 0x02},
{.opt = "--right-shift", .val = 0x20},
{.opt = "--left-alt", .val = 0x04},
{.opt = "--right-alt", .val = 0x40},
{.opt = "--left-meta", .val = 0x08},
{.opt = "--right-meta", .val = 0x80},
{.opt = NULL}
};
static struct options kval[] = {
{.opt = "--return", .val = 0x28},
{.opt = "--esc", .val = 0x29},
{.opt = "--bckspc", .val = 0x2a},
{.opt = "--tab", .val = 0x2b},
{.opt = "--spacebar", .val = 0x2c},
{.opt = "--caps-lock", .val = 0x39},
{.opt = "--f1", .val = 0x3a},
{.opt = "--f2", .val = 0x3b},
{.opt = "--f3", .val = 0x3c},
{.opt = "--f4", .val = 0x3d},
{.opt = "--f5", .val = 0x3e},
{.opt = "--f6", .val = 0x3f},
{.opt = "--f7", .val = 0x40},
{.opt = "--f8", .val = 0x41},
{.opt = "--f9", .val = 0x42},
{.opt = "--f10", .val = 0x43},
{.opt = "--f11", .val = 0x44},
{.opt = "--f12", .val = 0x45},
{.opt = "--insert", .val = 0x49},
{.opt = "--home", .val = 0x4a},
{.opt = "--pageup", .val = 0x4b},
{.opt = "--del", .val = 0x4c},
{.opt = "--end", .val = 0x4d},
{.opt = "--pagedown", .val = 0x4e},
{.opt = "--right", .val = 0x4f},
{.opt = "--left", .val = 0x50},
{.opt = "--down", .val = 0x51},
{.opt = "--kp-enter", .val = 0x58},
{.opt = "--up", .val = 0x52},
{.opt = "--num-lock", .val = 0x53},
{.opt = NULL}
};
int keyboard_fill_report(char report[8], char buf[BUF_LEN], int *hold)
{
char *tok = strtok(buf, " ");
int key = 0;
int i = 0;
for (; tok != NULL; tok = strtok(NULL, " ")) {
if (strcmp(tok, "--quit") == 0)
return -1;
if (strcmp(tok, "--hold") == 0) {
*hold = 1;
continue;
}
if (key < 6) {
for (i = 0; kval[i].opt != NULL; i++)
if (strcmp(tok, kval[i].opt) == 0) {
report[2 + key++] = kval[i].val;
break;
}
if (kval[i].opt != NULL)
continue;
}
if (key < 6)
if (islower(tok[0])) {
report[2 + key++] = (tok[0] - ('a' - 0x04));
continue;
}
for (i = 0; kmod[i].opt != NULL; i++)
if (strcmp(tok, kmod[i].opt) == 0) {
report[0] = report[0] | kmod[i].val;
break;
}
if (kmod[i].opt != NULL)
continue;
if (key < 6)
fprintf(stderr, "unknown option: %s\n", tok);
}
return 8;
}
static struct options mmod[] = {
{.opt = "--b1", .val = 0x01},
{.opt = "--b2", .val = 0x02},
{.opt = "--b3", .val = 0x04},
{.opt = NULL}
};
int mouse_fill_report(char report[8], char buf[BUF_LEN], int *hold)
{
char *tok = strtok(buf, " ");
int mvt = 0;
int i = 0;
for (; tok != NULL; tok = strtok(NULL, " ")) {
if (strcmp(tok, "--quit") == 0)
return -1;
if (strcmp(tok, "--hold") == 0) {
*hold = 1;
continue;
}
for (i = 0; mmod[i].opt != NULL; i++)
if (strcmp(tok, mmod[i].opt) == 0) {
report[0] = report[0] | mmod[i].val;
break;
}
if (mmod[i].opt != NULL)
continue;
if (!(tok[0] == '-' && tok[1] == '-') && mvt < 2) {
errno = 0;
report[1 + mvt++] = (char)strtol(tok, NULL, 0);
if (errno != 0) {
fprintf(stderr, "Bad value:'%s'\n", tok);
report[1 + mvt--] = 0;
}
continue;
}
fprintf(stderr, "unknown option: %s\n", tok);
}
return 3;
}
static struct options jmod[] = {
{.opt = "--b1", .val = 0x10},
{.opt = "--b2", .val = 0x20},
{.opt = "--b3", .val = 0x40},
{.opt = "--b4", .val = 0x80},
{.opt = "--hat1", .val = 0x00},
{.opt = "--hat2", .val = 0x01},
{.opt = "--hat3", .val = 0x02},
{.opt = "--hat4", .val = 0x03},
{.opt = "--hatneutral", .val = 0x04},
{.opt = NULL}
};
int joystick_fill_report(char report[8], char buf[BUF_LEN], int *hold)
{
char *tok = strtok(buf, " ");
int mvt = 0;
int i = 0;
*hold = 1;
/* set default hat position: neutral */
report[3] = 0x04;
for (; tok != NULL; tok = strtok(NULL, " ")) {
if (strcmp(tok, "--quit") == 0)
return -1;
for (i = 0; jmod[i].opt != NULL; i++)
if (strcmp(tok, jmod[i].opt) == 0) {
report[3] = (report[3] & 0xF0) | jmod[i].val;
break;
}
if (jmod[i].opt != NULL)
continue;
if (!(tok[0] == '-' && tok[1] == '-') && mvt < 3) {
errno = 0;
report[mvt++] = (char)strtol(tok, NULL, 0);
if (errno != 0) {
fprintf(stderr, "Bad value:'%s'\n", tok);
report[mvt--] = 0;
}
continue;
}
fprintf(stderr, "unknown option: %s\n", tok);
}
return 4;
}
void print_options(char c)
{
int i = 0;
if (c == 'k') {
printf(" keyboard options:\n"
" --hold\n");
for (i = 0; kmod[i].opt != NULL; i++)
printf("\t\t%s\n", kmod[i].opt);
printf("\n keyboard values:\n"
" [a-z] or\n");
for (i = 0; kval[i].opt != NULL; i++)
printf("\t\t%-8s%s", kval[i].opt, i % 2 ? "\n" : "");
printf("\n");
} else if (c == 'm') {
printf(" mouse options:\n"
" --hold\n");
for (i = 0; mmod[i].opt != NULL; i++)
printf("\t\t%s\n", mmod[i].opt);
printf("\n mouse values:\n"
" Two signed numbers\n"
"--quit to close\n");
} else {
printf(" joystick options:\n");
for (i = 0; jmod[i].opt != NULL; i++)
printf("\t\t%s\n", jmod[i].opt);
printf("\n joystick values:\n"
" three signed numbers\n"
"--quit to close\n");
}
}
int main(int argc, const char *argv[])
{
const char *filename = NULL;
int fd = 0;
char buf[BUF_LEN];
int cmd_len;
char report[8];
int to_send = 8;
int hold = 0;
fd_set rfds;
int retval, i;
if (argc < 3) {
fprintf(stderr, "Usage: %s devname mouse|keyboard|joystick\n",
argv[0]);
return 1;
}
if (argv[2][0] != 'k' && argv[2][0] != 'm' && argv[2][0] != 'j')
return 2;
filename = argv[1];
if ((fd = open(filename, O_RDWR, 0666)) == -1) {
perror(filename);
return 3;
}
print_options(argv[2][0]);
while (42) {
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
FD_SET(fd, &rfds);
retval = select(fd + 1, &rfds, NULL, NULL, NULL);
if (retval == -1 && errno == EINTR)
continue;
if (retval < 0) {
perror("select()");
return 4;
}
if (FD_ISSET(fd, &rfds)) {
cmd_len = read(fd, buf, BUF_LEN - 1);
printf("recv report:");
for (i = 0; i < cmd_len; i++)
printf(" %02x", buf[i]);
printf("\n");
}
if (FD_ISSET(STDIN_FILENO, &rfds)) {
memset(report, 0x0, sizeof(report));
cmd_len = read(STDIN_FILENO, buf, BUF_LEN - 1);
if (cmd_len == 0)
break;
buf[cmd_len - 1] = '\0';
hold = 0;
memset(report, 0x0, sizeof(report));
if (argv[2][0] == 'k')
to_send = keyboard_fill_report(report, buf, &hold);
else if (argv[2][0] == 'm')
to_send = mouse_fill_report(report, buf, &hold);
else
to_send = joystick_fill_report(report, buf, &hold);
if (to_send == -1)
break;
if (write(fd, report, to_send) != to_send) {
perror(filename);
return 5;
}
if (!hold) {
memset(report, 0x0, sizeof(report));
if (write(fd, report, to_send) != to_send) {
perror(filename);
return 6;
}
}
}
}
close(fd);
return 0;
}

View File

@ -107,7 +107,9 @@ allowed to issue dynamic suspends.
The user interface for controlling dynamic PM is located in the power/
subdirectory of each USB device's sysfs directory, that is, in
/sys/bus/usb/devices/.../power/ where "..." is the device's ID. The
relevant attribute files are: wakeup, level, and autosuspend.
relevant attribute files are: wakeup, control, and autosuspend.
(There may also be a file named "level"; this file was deprecated
as of the 2.6.35 kernel and replaced by the "control" file.)
power/wakeup
@ -120,7 +122,7 @@ relevant attribute files are: wakeup, level, and autosuspend.
while the device is suspended, the change won't take
effect until the following suspend.)
power/level
power/control
This file contains one of two words: "on" or "auto".
You can write those words to the file to change the
@ -148,14 +150,15 @@ relevant attribute files are: wakeup, level, and autosuspend.
never to autosuspend. You can write a number to the
file to change the autosuspend idle-delay time.
Writing "-1" to power/autosuspend and writing "on" to power/level do
Writing "-1" to power/autosuspend and writing "on" to power/control do
essentially the same thing -- they both prevent the device from being
autosuspended. Yes, this is a redundancy in the API.
(In 2.6.21 writing "0" to power/autosuspend would prevent the device
from being autosuspended; the behavior was changed in 2.6.22. The
power/autosuspend attribute did not exist prior to 2.6.21, and the
power/level attribute did not exist prior to 2.6.22.)
power/level attribute did not exist prior to 2.6.22. power/control
was added in 2.6.34.)
Changing the default idle-delay time
@ -212,7 +215,7 @@ among printers and scanners, but plenty of other types of device have
the same deficiency.
For this reason, by default the kernel disables autosuspend (the
power/level attribute is initialized to "on") for all devices other
power/control attribute is initialized to "on") for all devices other
than hubs. Hubs, at least, appear to be reasonably well-behaved in
this regard.
@ -373,7 +376,7 @@ usb_autopm_put_interface() in its close or release routine. But other
patterns are possible.
The autosuspend attempts mentioned above will often fail for one
reason or another. For example, the power/level attribute might be
reason or another. For example, the power/control attribute might be
set to "on", or another interface in the same device might not be
idle. This is perfectly normal. If the reason for failure was that
the device hasn't been idle for long enough, a timer is scheduled to
@ -394,12 +397,12 @@ Drivers can enable autosuspend for their devices by calling
in their probe() routine, if they know that the device is capable of
suspending and resuming correctly. This is exactly equivalent to
writing "auto" to the device's power/level attribute. Likewise,
writing "auto" to the device's power/control attribute. Likewise,
drivers can disable autosuspend by calling
usb_disable_autosuspend(struct usb_device *udev);
This is exactly the same as writing "on" to the power/level attribute.
This is exactly the same as writing "on" to the power/control attribute.
Sometimes a driver needs to make sure that remote wakeup is enabled
during autosuspend. For example, there's not much point

View File

@ -194,6 +194,10 @@ FTDI Single Port Serial Driver
This is a single port DB-25 serial adapter.
Devices supported include:
-TripNav TN-200 USB GPS
-Navis Engineering Bureau CH-4711 USB GPS
For any questions or problems with this driver, please contact Bill Ryder.
@ -216,7 +220,7 @@ Cypress M8 CY4601 Family Serial Driver
Devices supported:
-DeLorme's USB Earthmate (SiRF Star II lp arch)
-DeLorme's USB Earthmate GPS (SiRF Star II lp arch)
-Cypress HID->COM RS232 adapter
Note: Cypress Semiconductor claims no affiliation with the
@ -392,9 +396,10 @@ REINER SCT cyberJack pinpad/e-com USB chipcard reader
Prolific PL2303 Driver
This driver supports any device that has the PL2303 chip from Prolific
in it. This includes a number of single port USB to serial
converters and USB GPS devices. Devices from Aten (the UC-232) and
IO-Data work with this driver, as does the DCU-11 mobile-phone cable.
in it. This includes a number of single port USB to serial converters,
more than 70% of USB GPS devices (in 2010), and some USB UPSes. Devices
from Aten (the UC-232) and IO-Data work with this driver, as does
the DCU-11 mobile-phone cable.
For any questions or problems with this driver, please contact Greg
Kroah-Hartman at greg@kroah.com
@ -435,6 +440,22 @@ Winchiphead CH341 Driver
For any questions or problems with this driver, please contact
frank@kingswood-consulting.co.uk.
Moschip MCS7720, MCS7715 driver
These chips are present in devices sold by various manufacturers, such as Syba
and Cables Unlimited. There may be others. The 7720 provides two serial
ports, and the 7715 provides one serial and one standard PC parallel port.
Support for the 7715's parallel port is enabled by a separate option, which
will not appear unless parallel port support is first enabled at the top-level
of the Device Drivers config menu. Currently only compatibility mode is
supported on the parallel port (no ECP/EPP).
TODO:
- Implement ECP/EPP modes for the parallel port.
- Baud rates higher than 115200 are currently broken.
- Devices with a single serial port based on the Moschip MCS7703 may work
with this driver with a simple addition to the usb_device_id table. I
don't have one of these devices, so I can't say for sure.
Generic Serial driver

View File

@ -702,6 +702,9 @@ static void __init omap3_evm_init(void)
omap_mux_init_gpio(21, OMAP_PIN_INPUT_PULLUP);
ehci_pdata.reset_gpio_port[1] = 21;
/* EVM REV >= E can supply 500mA with EXTVBUS programming */
musb_board_data.power = 500;
musb_board_data.extvbus = 1;
} else {
/* setup EHCI phy reset on MDC */
omap_mux_init_gpio(135, OMAP_PIN_OUTPUT);

View File

@ -236,3 +236,158 @@ void __init usb_ehci_init(const struct ehci_hcd_omap_platform_data *pdata)
#endif /* CONFIG_USB_EHCI_HCD */
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
static struct resource ohci_resources[] = {
{
.start = OMAP34XX_OHCI_BASE,
.end = OMAP34XX_OHCI_BASE + SZ_1K - 1,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP34XX_UHH_CONFIG_BASE,
.end = OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP34XX_USBTLL_BASE,
.end = OMAP34XX_USBTLL_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{ /* general IRQ */
.start = INT_34XX_OHCI_IRQ,
.flags = IORESOURCE_IRQ,
}
};
static u64 ohci_dmamask = DMA_BIT_MASK(32);
static struct platform_device ohci_device = {
.name = "ohci-omap3",
.id = 0,
.dev = {
.dma_mask = &ohci_dmamask,
.coherent_dma_mask = 0xffffffff,
},
.num_resources = ARRAY_SIZE(ohci_resources),
.resource = ohci_resources,
};
static void setup_ohci_io_mux(const enum ohci_omap3_port_mode *port_mode)
{
switch (port_mode[0]) {
case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
omap_mux_init_signal("mm1_rxdp",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("mm1_rxdm",
OMAP_PIN_INPUT_PULLDOWN);
/* FALLTHROUGH */
case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
omap_mux_init_signal("mm1_rxrcv",
OMAP_PIN_INPUT_PULLDOWN);
/* FALLTHROUGH */
case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
omap_mux_init_signal("mm1_txen_n", OMAP_PIN_OUTPUT);
/* FALLTHROUGH */
case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
omap_mux_init_signal("mm1_txse0",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("mm1_txdat",
OMAP_PIN_INPUT_PULLDOWN);
break;
case OMAP_OHCI_PORT_MODE_UNUSED:
/* FALLTHROUGH */
default:
break;
}
switch (port_mode[1]) {
case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
omap_mux_init_signal("mm2_rxdp",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("mm2_rxdm",
OMAP_PIN_INPUT_PULLDOWN);
/* FALLTHROUGH */
case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
omap_mux_init_signal("mm2_rxrcv",
OMAP_PIN_INPUT_PULLDOWN);
/* FALLTHROUGH */
case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
omap_mux_init_signal("mm2_txen_n", OMAP_PIN_OUTPUT);
/* FALLTHROUGH */
case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
omap_mux_init_signal("mm2_txse0",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("mm2_txdat",
OMAP_PIN_INPUT_PULLDOWN);
break;
case OMAP_OHCI_PORT_MODE_UNUSED:
/* FALLTHROUGH */
default:
break;
}
switch (port_mode[2]) {
case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
omap_mux_init_signal("mm3_rxdp",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("mm3_rxdm",
OMAP_PIN_INPUT_PULLDOWN);
/* FALLTHROUGH */
case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
omap_mux_init_signal("mm3_rxrcv",
OMAP_PIN_INPUT_PULLDOWN);
/* FALLTHROUGH */
case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
omap_mux_init_signal("mm3_txen_n", OMAP_PIN_OUTPUT);
/* FALLTHROUGH */
case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
omap_mux_init_signal("mm3_txse0",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("mm3_txdat",
OMAP_PIN_INPUT_PULLDOWN);
break;
case OMAP_OHCI_PORT_MODE_UNUSED:
/* FALLTHROUGH */
default:
break;
}
}
void __init usb_ohci_init(const struct ohci_hcd_omap_platform_data *pdata)
{
platform_device_add_data(&ohci_device, pdata, sizeof(*pdata));
/* Setup Pin IO MUX for OHCI */
if (cpu_is_omap34xx())
setup_ohci_io_mux(pdata->port_mode);
if (platform_device_register(&ohci_device) < 0) {
pr_err("Unable to register FS-USB (OHCI) device\n");
return;
}
}
#else
void __init usb_ohci_init(const struct ohci_hcd_omap_platform_data *pdata)
{
}
#endif /* CONFIG_USB_OHCI_HCD */

View File

@ -107,6 +107,7 @@ void __init usb_musb_init(struct omap_musb_board_data *board_data)
musb_plat.board_data = board_data;
musb_plat.power = board_data->power >> 1;
musb_plat.mode = board_data->mode;
musb_plat.extvbus = board_data->extvbus;
if (platform_device_register(&musb_device) < 0)
printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");

View File

@ -13,6 +13,20 @@ enum ehci_hcd_omap_mode {
EHCI_HCD_OMAP_MODE_TLL,
};
enum ohci_omap3_port_mode {
OMAP_OHCI_PORT_MODE_UNUSED,
OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0,
OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM,
OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0,
OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM,
OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0,
OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM,
OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0,
OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM,
OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0,
OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM,
};
struct ehci_hcd_omap_platform_data {
enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS];
unsigned phy_reset:1;
@ -21,6 +35,13 @@ struct ehci_hcd_omap_platform_data {
int reset_gpio_port[OMAP3_HS_USB_PORTS];
};
struct ohci_hcd_omap_platform_data {
enum ohci_omap3_port_mode port_mode[OMAP3_HS_USB_PORTS];
/* Set this to true for ES2.x silicon */
unsigned es2_compatibility:1;
};
/*-------------------------------------------------------------------------*/
#define OMAP1_OTG_BASE 0xfffb0400
@ -47,6 +68,7 @@ struct omap_musb_board_data {
u8 interface_type;
u8 mode;
u16 power;
unsigned extvbus:1;
};
enum musb_interface {MUSB_INTERFACE_ULPI, MUSB_INTERFACE_UTMI};
@ -55,6 +77,8 @@ extern void usb_musb_init(struct omap_musb_board_data *board_data);
extern void usb_ehci_init(const struct ehci_hcd_omap_platform_data *pdata);
extern void usb_ohci_init(const struct ohci_hcd_omap_platform_data *pdata);
#endif
void omap_usb_init(struct omap_usb_config *pdata);

View File

@ -783,13 +783,12 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
{
struct usbhid_device *usbhid = hid->driver_data;
usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
usbhid->inbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
&usbhid->inbuf_dma);
usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
usbhid->outbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
&usbhid->outbuf_dma);
usbhid->cr = usb_buffer_alloc(dev, sizeof(*usbhid->cr), GFP_KERNEL,
&usbhid->cr_dma);
usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
usbhid->cr = kmalloc(sizeof(*usbhid->cr), GFP_KERNEL);
usbhid->ctrlbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
&usbhid->ctrlbuf_dma);
if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr ||
!usbhid->ctrlbuf)
@ -844,10 +843,10 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
{
struct usbhid_device *usbhid = hid->driver_data;
usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
usb_free_coherent(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
usb_free_coherent(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
kfree(usbhid->cr);
usb_free_coherent(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
}
static int usbhid_parse(struct hid_device *hid)
@ -1007,9 +1006,8 @@ static int usbhid_start(struct hid_device *hid)
usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr,
usbhid->ctrlbuf, 1, hid_ctrl, hid);
usbhid->urbctrl->setup_dma = usbhid->cr_dma;
usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
usbhid->urbctrl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS))
usbhid_init_reports(hid);

View File

@ -75,7 +75,6 @@ struct usbhid_device {
struct urb *urbctrl; /* Control URB */
struct usb_ctrlrequest *cr; /* Control request struct */
dma_addr_t cr_dma; /* Control request struct dma */
struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */
unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */
char *ctrlbuf; /* Control buffer */

View File

@ -74,7 +74,6 @@ struct usb_kbd {
unsigned char *new;
struct usb_ctrlrequest *cr;
unsigned char *leds;
dma_addr_t cr_dma;
dma_addr_t new_dma;
dma_addr_t leds_dma;
};
@ -197,11 +196,11 @@ static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
return -1;
if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL)))
return -1;
if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma)))
if (!(kbd->new = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &kbd->new_dma)))
return -1;
if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), GFP_ATOMIC, &kbd->cr_dma)))
if (!(kbd->cr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
return -1;
if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma)))
if (!(kbd->leds = usb_alloc_coherent(dev, 1, GFP_ATOMIC, &kbd->leds_dma)))
return -1;
return 0;
@ -211,9 +210,9 @@ static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
{
usb_free_urb(kbd->irq);
usb_free_urb(kbd->led);
usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma);
usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma);
usb_free_coherent(dev, 8, kbd->new, kbd->new_dma);
kfree(kbd->cr);
usb_free_coherent(dev, 1, kbd->leds, kbd->leds_dma);
}
static int usb_kbd_probe(struct usb_interface *iface,
@ -304,9 +303,8 @@ static int usb_kbd_probe(struct usb_interface *iface,
usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
(void *) kbd->cr, kbd->leds, 1,
usb_kbd_led, kbd);
kbd->led->setup_dma = kbd->cr_dma;
kbd->led->transfer_dma = kbd->leds_dma;
kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
kbd->led->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
error = input_register_device(kbd->dev);
if (error)

View File

@ -142,7 +142,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
if (!mouse || !input_dev)
goto fail1;
mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma);
mouse->data = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &mouse->data_dma);
if (!mouse->data)
goto fail1;
@ -205,7 +205,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
fail3:
usb_free_urb(mouse->irq);
fail2:
usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
usb_free_coherent(dev, 8, mouse->data, mouse->data_dma);
fail1:
input_free_device(input_dev);
kfree(mouse);
@ -221,7 +221,7 @@ static void usb_mouse_disconnect(struct usb_interface *intf)
usb_kill_urb(mouse->irq);
input_unregister_device(mouse->dev);
usb_free_urb(mouse->irq);
usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);
usb_free_coherent(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);
kfree(mouse);
}
}

View File

@ -533,8 +533,8 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
return 0;
xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN,
GFP_KERNEL, &xpad->odata_dma);
xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,
GFP_KERNEL, &xpad->odata_dma);
if (!xpad->odata)
goto fail1;
@ -554,7 +554,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
return 0;
fail2: usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
fail2: usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
fail1: return error;
}
@ -568,7 +568,7 @@ static void xpad_deinit_output(struct usb_xpad *xpad)
{
if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) {
usb_free_urb(xpad->irq_out);
usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
xpad->odata, xpad->odata_dma);
}
}
@ -788,8 +788,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
if (!xpad || !input_dev)
goto fail1;
xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
GFP_KERNEL, &xpad->idata_dma);
xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN,
GFP_KERNEL, &xpad->idata_dma);
if (!xpad->idata)
goto fail1;
@ -942,7 +942,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
fail5: usb_kill_urb(xpad->irq_in);
fail4: usb_free_urb(xpad->irq_in);
fail3: xpad_deinit_output(xpad);
fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
fail2: usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
fail1: input_free_device(input_dev);
kfree(xpad);
return error;
@ -964,7 +964,7 @@ static void xpad_disconnect(struct usb_interface *intf)
usb_kill_urb(xpad->irq_in);
}
usb_free_urb(xpad->irq_in);
usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
xpad->idata, xpad->idata_dma);
kfree(xpad);
}

View File

@ -624,13 +624,13 @@ static void ati_remote_irq_in(struct urb *urb)
static int ati_remote_alloc_buffers(struct usb_device *udev,
struct ati_remote *ati_remote)
{
ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC,
&ati_remote->inbuf_dma);
ati_remote->inbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
&ati_remote->inbuf_dma);
if (!ati_remote->inbuf)
return -1;
ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC,
&ati_remote->outbuf_dma);
ati_remote->outbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
&ati_remote->outbuf_dma);
if (!ati_remote->outbuf)
return -1;
@ -653,10 +653,10 @@ static void ati_remote_free_buffers(struct ati_remote *ati_remote)
usb_free_urb(ati_remote->irq_urb);
usb_free_urb(ati_remote->out_urb);
usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
usb_free_coherent(ati_remote->udev, DATA_BUFSIZE,
ati_remote->inbuf, ati_remote->inbuf_dma);
usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
usb_free_coherent(ati_remote->udev, DATA_BUFSIZE,
ati_remote->outbuf, ati_remote->outbuf_dma);
}

View File

@ -589,7 +589,7 @@ static int ati_remote2_urb_init(struct ati_remote2 *ar2)
int i, pipe, maxp;
for (i = 0; i < 2; i++) {
ar2->buf[i] = usb_buffer_alloc(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]);
ar2->buf[i] = usb_alloc_coherent(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]);
if (!ar2->buf[i])
return -ENOMEM;
@ -617,7 +617,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2)
for (i = 0; i < 2; i++) {
usb_free_urb(ar2->urb[i]);
usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);
usb_free_coherent(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);
}
}

View File

@ -102,7 +102,6 @@ struct cm109_dev {
struct cm109_ctl_packet *ctl_data;
dma_addr_t ctl_dma;
struct usb_ctrlrequest *ctl_req;
dma_addr_t ctl_req_dma;
struct urb *urb_ctl;
/*
* The 3 bitfields below are protected by ctl_submit_lock.
@ -629,15 +628,13 @@ static const struct usb_device_id cm109_usb_table[] = {
static void cm109_usb_cleanup(struct cm109_dev *dev)
{
if (dev->ctl_req)
usb_buffer_free(dev->udev, sizeof(*(dev->ctl_req)),
dev->ctl_req, dev->ctl_req_dma);
kfree(dev->ctl_req);
if (dev->ctl_data)
usb_buffer_free(dev->udev, USB_PKT_LEN,
dev->ctl_data, dev->ctl_dma);
usb_free_coherent(dev->udev, USB_PKT_LEN,
dev->ctl_data, dev->ctl_dma);
if (dev->irq_data)
usb_buffer_free(dev->udev, USB_PKT_LEN,
dev->irq_data, dev->irq_dma);
usb_free_coherent(dev->udev, USB_PKT_LEN,
dev->irq_data, dev->irq_dma);
usb_free_urb(dev->urb_irq); /* parameter validation in core/urb */
usb_free_urb(dev->urb_ctl); /* parameter validation in core/urb */
@ -686,18 +683,17 @@ static int cm109_usb_probe(struct usb_interface *intf,
goto err_out;
/* allocate usb buffers */
dev->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN,
GFP_KERNEL, &dev->irq_dma);
dev->irq_data = usb_alloc_coherent(udev, USB_PKT_LEN,
GFP_KERNEL, &dev->irq_dma);
if (!dev->irq_data)
goto err_out;
dev->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN,
GFP_KERNEL, &dev->ctl_dma);
dev->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN,
GFP_KERNEL, &dev->ctl_dma);
if (!dev->ctl_data)
goto err_out;
dev->ctl_req = usb_buffer_alloc(udev, sizeof(*(dev->ctl_req)),
GFP_KERNEL, &dev->ctl_req_dma);
dev->ctl_req = kmalloc(sizeof(*(dev->ctl_req)), GFP_KERNEL);
if (!dev->ctl_req)
goto err_out;
@ -735,10 +731,8 @@ static int cm109_usb_probe(struct usb_interface *intf,
usb_fill_control_urb(dev->urb_ctl, udev, usb_sndctrlpipe(udev, 0),
(void *)dev->ctl_req, dev->ctl_data, USB_PKT_LEN,
cm109_urb_ctl_callback, dev);
dev->urb_ctl->setup_dma = dev->ctl_req_dma;
dev->urb_ctl->transfer_dma = dev->ctl_dma;
dev->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP |
URB_NO_TRANSFER_DMA_MAP;
dev->urb_ctl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
dev->urb_ctl->dev = udev;
/* find out the physical bus location */

View File

@ -464,7 +464,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
remote->in_endpoint = endpoint;
remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */
remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma);
remote->in_buffer = usb_alloc_coherent(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma);
if (!remote->in_buffer) {
error = -ENOMEM;
goto fail1;
@ -543,7 +543,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
return 0;
fail3: usb_free_urb(remote->irq_urb);
fail2: usb_buffer_free(udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
fail2: usb_free_coherent(udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
fail1: kfree(remote);
input_free_device(input_dev);
@ -564,7 +564,7 @@ static void keyspan_disconnect(struct usb_interface *interface)
input_unregister_device(remote->input);
usb_kill_urb(remote->irq_urb);
usb_free_urb(remote->irq_urb);
usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
usb_free_coherent(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
kfree(remote);
}
}

View File

@ -64,7 +64,6 @@ struct powermate_device {
dma_addr_t data_dma;
struct urb *irq, *config;
struct usb_ctrlrequest *configcr;
dma_addr_t configcr_dma;
struct usb_device *udev;
struct input_dev *input;
spinlock_t lock;
@ -182,8 +181,6 @@ static void powermate_sync_state(struct powermate_device *pm)
usb_fill_control_urb(pm->config, pm->udev, usb_sndctrlpipe(pm->udev, 0),
(void *) pm->configcr, NULL, 0,
powermate_config_complete, pm);
pm->config->setup_dma = pm->configcr_dma;
pm->config->transfer_flags |= URB_NO_SETUP_DMA_MAP;
if (usb_submit_urb(pm->config, GFP_ATOMIC))
printk(KERN_ERR "powermate: usb_submit_urb(config) failed");
@ -276,13 +273,12 @@ static int powermate_input_event(struct input_dev *dev, unsigned int type, unsig
static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm)
{
pm->data = usb_buffer_alloc(udev, POWERMATE_PAYLOAD_SIZE_MAX,
GFP_ATOMIC, &pm->data_dma);
pm->data = usb_alloc_coherent(udev, POWERMATE_PAYLOAD_SIZE_MAX,
GFP_ATOMIC, &pm->data_dma);
if (!pm->data)
return -1;
pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)),
GFP_ATOMIC, &pm->configcr_dma);
pm->configcr = kmalloc(sizeof(*(pm->configcr)), GFP_KERNEL);
if (!pm->configcr)
return -1;
@ -291,10 +287,9 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev
static void powermate_free_buffers(struct usb_device *udev, struct powermate_device *pm)
{
usb_buffer_free(udev, POWERMATE_PAYLOAD_SIZE_MAX,
pm->data, pm->data_dma);
usb_buffer_free(udev, sizeof(*(pm->configcr)),
pm->configcr, pm->configcr_dma);
usb_free_coherent(udev, POWERMATE_PAYLOAD_SIZE_MAX,
pm->data, pm->data_dma);
kfree(pm->configcr);
}
/* Called whenever a USB device matching one in our supported devices table is connected */

View File

@ -111,7 +111,6 @@ struct yealink_dev {
struct yld_ctl_packet *ctl_data;
dma_addr_t ctl_dma;
struct usb_ctrlrequest *ctl_req;
dma_addr_t ctl_req_dma;
struct urb *urb_ctl;
char phys[64]; /* physical device path */
@ -836,12 +835,9 @@ static int usb_cleanup(struct yealink_dev *yld, int err)
usb_free_urb(yld->urb_irq);
usb_free_urb(yld->urb_ctl);
usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)),
yld->ctl_req, yld->ctl_req_dma);
usb_buffer_free(yld->udev, USB_PKT_LEN,
yld->ctl_data, yld->ctl_dma);
usb_buffer_free(yld->udev, USB_PKT_LEN,
yld->irq_data, yld->irq_dma);
kfree(yld->ctl_req);
usb_free_coherent(yld->udev, USB_PKT_LEN, yld->ctl_data, yld->ctl_dma);
usb_free_coherent(yld->udev, USB_PKT_LEN, yld->irq_data, yld->irq_dma);
kfree(yld);
return err;
@ -886,18 +882,17 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
return usb_cleanup(yld, -ENOMEM);
/* allocate usb buffers */
yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN,
GFP_ATOMIC, &yld->irq_dma);
yld->irq_data = usb_alloc_coherent(udev, USB_PKT_LEN,
GFP_ATOMIC, &yld->irq_dma);
if (yld->irq_data == NULL)
return usb_cleanup(yld, -ENOMEM);
yld->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN,
GFP_ATOMIC, &yld->ctl_dma);
yld->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN,
GFP_ATOMIC, &yld->ctl_dma);
if (!yld->ctl_data)
return usb_cleanup(yld, -ENOMEM);
yld->ctl_req = usb_buffer_alloc(udev, sizeof(*(yld->ctl_req)),
GFP_ATOMIC, &yld->ctl_req_dma);
yld->ctl_req = kmalloc(sizeof(*(yld->ctl_req)), GFP_KERNEL);
if (yld->ctl_req == NULL)
return usb_cleanup(yld, -ENOMEM);
@ -936,10 +931,8 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
usb_fill_control_urb(yld->urb_ctl, udev, usb_sndctrlpipe(udev, 0),
(void *)yld->ctl_req, yld->ctl_data, USB_PKT_LEN,
urb_ctl_callback, yld);
yld->urb_ctl->setup_dma = yld->ctl_req_dma;
yld->urb_ctl->transfer_dma = yld->ctl_dma;
yld->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP |
URB_NO_TRANSFER_DMA_MAP;
yld->urb_ctl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
yld->urb_ctl->dev = udev;
/* find out the physical bus location */

View File

@ -806,8 +806,8 @@ static int atp_probe(struct usb_interface *iface,
if (!dev->urb)
goto err_free_devs;
dev->data = usb_buffer_alloc(dev->udev, dev->info->datalen, GFP_KERNEL,
&dev->urb->transfer_dma);
dev->data = usb_alloc_coherent(dev->udev, dev->info->datalen, GFP_KERNEL,
&dev->urb->transfer_dma);
if (!dev->data)
goto err_free_urb;
@ -862,8 +862,8 @@ static int atp_probe(struct usb_interface *iface,
return 0;
err_free_buffer:
usb_buffer_free(dev->udev, dev->info->datalen,
dev->data, dev->urb->transfer_dma);
usb_free_coherent(dev->udev, dev->info->datalen,
dev->data, dev->urb->transfer_dma);
err_free_urb:
usb_free_urb(dev->urb);
err_free_devs:
@ -881,8 +881,8 @@ static void atp_disconnect(struct usb_interface *iface)
if (dev) {
usb_kill_urb(dev->urb);
input_unregister_device(dev->input);
usb_buffer_free(dev->udev, dev->info->datalen,
dev->data, dev->urb->transfer_dma);
usb_free_coherent(dev->udev, dev->info->datalen,
dev->data, dev->urb->transfer_dma);
usb_free_urb(dev->urb);
kfree(dev);
}

View File

@ -715,15 +715,15 @@ static int bcm5974_probe(struct usb_interface *iface,
if (!dev->tp_urb)
goto err_free_bt_urb;
dev->bt_data = usb_buffer_alloc(dev->udev,
dev->cfg.bt_datalen, GFP_KERNEL,
&dev->bt_urb->transfer_dma);
dev->bt_data = usb_alloc_coherent(dev->udev,
dev->cfg.bt_datalen, GFP_KERNEL,
&dev->bt_urb->transfer_dma);
if (!dev->bt_data)
goto err_free_urb;
dev->tp_data = usb_buffer_alloc(dev->udev,
dev->cfg.tp_datalen, GFP_KERNEL,
&dev->tp_urb->transfer_dma);
dev->tp_data = usb_alloc_coherent(dev->udev,
dev->cfg.tp_datalen, GFP_KERNEL,
&dev->tp_urb->transfer_dma);
if (!dev->tp_data)
goto err_free_bt_buffer;
@ -765,10 +765,10 @@ static int bcm5974_probe(struct usb_interface *iface,
return 0;
err_free_buffer:
usb_buffer_free(dev->udev, dev->cfg.tp_datalen,
usb_free_coherent(dev->udev, dev->cfg.tp_datalen,
dev->tp_data, dev->tp_urb->transfer_dma);
err_free_bt_buffer:
usb_buffer_free(dev->udev, dev->cfg.bt_datalen,
usb_free_coherent(dev->udev, dev->cfg.bt_datalen,
dev->bt_data, dev->bt_urb->transfer_dma);
err_free_urb:
usb_free_urb(dev->tp_urb);
@ -788,10 +788,10 @@ static void bcm5974_disconnect(struct usb_interface *iface)
usb_set_intfdata(iface, NULL);
input_unregister_device(dev->input);
usb_buffer_free(dev->udev, dev->cfg.tp_datalen,
dev->tp_data, dev->tp_urb->transfer_dma);
usb_buffer_free(dev->udev, dev->cfg.bt_datalen,
dev->bt_data, dev->bt_urb->transfer_dma);
usb_free_coherent(dev->udev, dev->cfg.tp_datalen,
dev->tp_data, dev->tp_urb->transfer_dma);
usb_free_coherent(dev->udev, dev->cfg.bt_datalen,
dev->bt_data, dev->bt_urb->transfer_dma);
usb_free_urb(dev->tp_urb);
usb_free_urb(dev->bt_urb);
kfree(dev);

View File

@ -155,7 +155,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
goto fail1;
}
acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma);
acecad->data = usb_alloc_coherent(dev, 8, GFP_KERNEL, &acecad->data_dma);
if (!acecad->data) {
err= -ENOMEM;
goto fail1;
@ -235,7 +235,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
return 0;
fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma);
fail2: usb_free_coherent(dev, 8, acecad->data, acecad->data_dma);
fail1: input_free_device(input_dev);
kfree(acecad);
return err;
@ -249,7 +249,7 @@ static void usb_acecad_disconnect(struct usb_interface *intf)
input_unregister_device(acecad->input);
usb_free_urb(acecad->irq);
usb_buffer_free(acecad->usbdev, 8, acecad->data, acecad->data_dma);
usb_free_coherent(acecad->usbdev, 8, acecad->data, acecad->data_dma);
kfree(acecad);
}

View File

@ -1711,8 +1711,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
goto fail1;
}
aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,
GFP_ATOMIC, &aiptek->data_dma);
aiptek->data = usb_alloc_coherent(usbdev, AIPTEK_PACKET_LENGTH,
GFP_ATOMIC, &aiptek->data_dma);
if (!aiptek->data) {
dev_warn(&intf->dev, "cannot allocate usb buffer\n");
goto fail1;
@ -1884,8 +1884,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
fail4: sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
fail3: usb_free_urb(aiptek->urb);
fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
aiptek->data_dma);
fail2: usb_free_coherent(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
aiptek->data_dma);
fail1: usb_set_intfdata(intf, NULL);
input_free_device(inputdev);
kfree(aiptek);
@ -1909,9 +1909,9 @@ static void aiptek_disconnect(struct usb_interface *intf)
input_unregister_device(aiptek->inputdev);
sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
usb_free_urb(aiptek->urb);
usb_buffer_free(interface_to_usbdev(intf),
AIPTEK_PACKET_LENGTH,
aiptek->data, aiptek->data_dma);
usb_free_coherent(interface_to_usbdev(intf),
AIPTEK_PACKET_LENGTH,
aiptek->data, aiptek->data_dma);
kfree(aiptek);
}
}

View File

@ -850,8 +850,8 @@ static int gtco_probe(struct usb_interface *usbinterface,
gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface));
/* Allocate some data for incoming reports */
gtco->buffer = usb_buffer_alloc(gtco->usbdev, REPORT_MAX_SIZE,
GFP_KERNEL, &gtco->buf_dma);
gtco->buffer = usb_alloc_coherent(gtco->usbdev, REPORT_MAX_SIZE,
GFP_KERNEL, &gtco->buf_dma);
if (!gtco->buffer) {
err("No more memory for us buffers");
error = -ENOMEM;
@ -982,8 +982,8 @@ static int gtco_probe(struct usb_interface *usbinterface,
err_free_urb:
usb_free_urb(gtco->urbinfo);
err_free_buf:
usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE,
gtco->buffer, gtco->buf_dma);
usb_free_coherent(gtco->usbdev, REPORT_MAX_SIZE,
gtco->buffer, gtco->buf_dma);
err_free_devs:
input_free_device(input_dev);
kfree(gtco);
@ -1005,8 +1005,8 @@ static void gtco_disconnect(struct usb_interface *interface)
input_unregister_device(gtco->inputdevice);
usb_kill_urb(gtco->urbinfo);
usb_free_urb(gtco->urbinfo);
usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE,
gtco->buffer, gtco->buf_dma);
usb_free_coherent(gtco->usbdev, REPORT_MAX_SIZE,
gtco->buffer, gtco->buf_dma);
kfree(gtco);
}

View File

@ -122,7 +122,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
if (!kbtab || !input_dev)
goto fail1;
kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma);
kbtab->data = usb_alloc_coherent(dev, 8, GFP_KERNEL, &kbtab->data_dma);
if (!kbtab->data)
goto fail1;
@ -173,7 +173,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
return 0;
fail3: usb_free_urb(kbtab->irq);
fail2: usb_buffer_free(dev, 8, kbtab->data, kbtab->data_dma);
fail2: usb_free_coherent(dev, 8, kbtab->data, kbtab->data_dma);
fail1: input_free_device(input_dev);
kfree(kbtab);
return error;
@ -187,7 +187,7 @@ static void kbtab_disconnect(struct usb_interface *intf)
input_unregister_device(kbtab->dev);
usb_free_urb(kbtab->irq);
usb_buffer_free(kbtab->usbdev, 8, kbtab->data, kbtab->data_dma);
usb_free_coherent(kbtab->usbdev, 8, kbtab->data, kbtab->data_dma);
kfree(kbtab);
}

View File

@ -465,8 +465,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
goto fail1;
}
wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX,
GFP_KERNEL, &wacom->data_dma);
wacom_wac->data = usb_alloc_coherent(dev, WACOM_PKGLEN_MAX,
GFP_KERNEL, &wacom->data_dma);
if (!wacom_wac->data) {
error = -ENOMEM;
goto fail1;
@ -536,7 +536,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
fail4: wacom_remove_shared_data(wacom_wac);
fail3: usb_free_urb(wacom->irq);
fail2: usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
fail1: input_free_device(input_dev);
kfree(wacom);
return error;
@ -551,7 +551,7 @@ static void wacom_disconnect(struct usb_interface *intf)
usb_kill_urb(wacom->irq);
input_unregister_device(wacom->wacom_wac.input);
usb_free_urb(wacom->irq);
usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
wacom->wacom_wac.data, wacom->data_dma);
wacom_remove_shared_data(&wacom->wacom_wac);
kfree(wacom);

View File

@ -1290,8 +1290,8 @@ static void usbtouch_close(struct input_dev *input)
static void usbtouch_free_buffers(struct usb_device *udev,
struct usbtouch_usb *usbtouch)
{
usb_buffer_free(udev, usbtouch->type->rept_size,
usbtouch->data, usbtouch->data_dma);
usb_free_coherent(udev, usbtouch->type->rept_size,
usbtouch->data, usbtouch->data_dma);
kfree(usbtouch->buffer);
}
@ -1335,8 +1335,8 @@ static int usbtouch_probe(struct usb_interface *intf,
if (!type->process_pkt)
type->process_pkt = usbtouch_process_pkt;
usbtouch->data = usb_buffer_alloc(udev, type->rept_size,
GFP_KERNEL, &usbtouch->data_dma);
usbtouch->data = usb_alloc_coherent(udev, type->rept_size,
GFP_KERNEL, &usbtouch->data_dma);
if (!usbtouch->data)
goto out_free;

View File

@ -96,8 +96,9 @@ static int usb_free_stream_buffers(struct usb_data_stream *stream)
while (stream->buf_num) {
stream->buf_num--;
deb_mem("freeing buffer %d\n",stream->buf_num);
usb_buffer_free(stream->udev, stream->buf_size,
stream->buf_list[stream->buf_num], stream->dma_addr[stream->buf_num]);
usb_free_coherent(stream->udev, stream->buf_size,
stream->buf_list[stream->buf_num],
stream->dma_addr[stream->buf_num]);
}
}
@ -116,7 +117,7 @@ static int usb_allocate_stream_buffers(struct usb_data_stream *stream, int num,
for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) {
deb_mem("allocating buffer %d\n",stream->buf_num);
if (( stream->buf_list[stream->buf_num] =
usb_buffer_alloc(stream->udev, size, GFP_ATOMIC,
usb_alloc_coherent(stream->udev, size, GFP_ATOMIC,
&stream->dma_addr[stream->buf_num]) ) == NULL) {
deb_mem("not enough memory for urb-buffer allocation.\n");
usb_free_stream_buffers(stream);

View File

@ -1257,7 +1257,7 @@ static int ttusb_dec_init_usb(struct ttusb_dec *dec)
if(!dec->irq_urb) {
return -ENOMEM;
}
dec->irq_buffer = usb_buffer_alloc(dec->udev,IRQ_PACKET_SIZE,
dec->irq_buffer = usb_alloc_coherent(dec->udev,IRQ_PACKET_SIZE,
GFP_ATOMIC, &dec->irq_dma_handle);
if(!dec->irq_buffer) {
usb_free_urb(dec->irq_urb);
@ -1550,8 +1550,8 @@ static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
usb_free_urb(dec->irq_urb);
usb_buffer_free(dec->udev,IRQ_PACKET_SIZE,
dec->irq_buffer, dec->irq_dma_handle);
usb_free_coherent(dec->udev,IRQ_PACKET_SIZE,
dec->irq_buffer, dec->irq_dma_handle);
if (dec->rc_input_dev) {
input_unregister_device(dec->rc_input_dev);

View File

@ -177,7 +177,7 @@ void au0828_uninit_isoc(struct au0828_dev *dev)
usb_unlink_urb(urb);
if (dev->isoc_ctl.transfer_buffer[i]) {
usb_buffer_free(dev->usbdev,
usb_free_coherent(dev->usbdev,
urb->transfer_buffer_length,
dev->isoc_ctl.transfer_buffer[i],
urb->transfer_dma);
@ -247,7 +247,7 @@ int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
}
dev->isoc_ctl.urb[i] = urb;
dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->usbdev,
dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->usbdev,
sb_size, GFP_KERNEL, &urb->transfer_dma);
if (!dev->isoc_ctl.transfer_buffer[i]) {
printk("unable to allocate %i bytes for transfer"

View File

@ -676,11 +676,11 @@ void cx231xx_uninit_isoc(struct cx231xx *dev)
usb_unlink_urb(urb);
if (dev->video_mode.isoc_ctl.transfer_buffer[i]) {
usb_buffer_free(dev->udev,
urb->transfer_buffer_length,
dev->video_mode.isoc_ctl.
transfer_buffer[i],
urb->transfer_dma);
usb_free_coherent(dev->udev,
urb->transfer_buffer_length,
dev->video_mode.isoc_ctl.
transfer_buffer[i],
urb->transfer_dma);
}
usb_free_urb(urb);
dev->video_mode.isoc_ctl.urb[i] = NULL;
@ -767,8 +767,8 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
dev->video_mode.isoc_ctl.urb[i] = urb;
dev->video_mode.isoc_ctl.transfer_buffer[i] =
usb_buffer_alloc(dev->udev, sb_size, GFP_KERNEL,
&urb->transfer_dma);
usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,
&urb->transfer_dma);
if (!dev->video_mode.isoc_ctl.transfer_buffer[i]) {
cx231xx_err("unable to allocate %i bytes for transfer"
" buffer %i%s\n",

View File

@ -970,7 +970,7 @@ void em28xx_uninit_isoc(struct em28xx *dev)
usb_unlink_urb(urb);
if (dev->isoc_ctl.transfer_buffer[i]) {
usb_buffer_free(dev->udev,
usb_free_coherent(dev->udev,
urb->transfer_buffer_length,
dev->isoc_ctl.transfer_buffer[i],
urb->transfer_dma);
@ -1045,7 +1045,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,
}
dev->isoc_ctl.urb[i] = urb;
dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev,
dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev,
sb_size, GFP_KERNEL, &urb->transfer_dma);
if (!dev->isoc_ctl.transfer_buffer[i]) {
em28xx_err("unable to allocate %i bytes for transfer"

View File

@ -117,13 +117,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
return -ENOMEM;
}
gspca_dev->urb[n] = urb;
urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
SD_PKT_SZ * SD_NPKT,
GFP_KERNEL,
&urb->transfer_dma);
if (urb->transfer_buffer == NULL) {
err("usb_buffer_alloc failed");
err("usb_alloc_coherent failed");
return -ENOMEM;
}
urb->dev = gspca_dev->dev;

View File

@ -213,7 +213,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
goto error;
}
buffer = usb_buffer_alloc(dev, buffer_len,
buffer = usb_alloc_coherent(dev, buffer_len,
GFP_KERNEL, &urb->transfer_dma);
if (!buffer) {
ret = -ENOMEM;
@ -232,10 +232,10 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
return ret;
error_submit:
usb_buffer_free(dev,
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);
usb_free_coherent(dev,
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);
error_buffer:
usb_free_urb(urb);
error:
@ -272,10 +272,10 @@ static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev)
if (urb) {
gspca_dev->int_urb = NULL;
usb_kill_urb(urb);
usb_buffer_free(gspca_dev->dev,
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);
usb_free_coherent(gspca_dev->dev,
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);
usb_free_urb(urb);
}
}
@ -605,10 +605,10 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
gspca_dev->urb[i] = NULL;
usb_kill_urb(urb);
if (urb->transfer_buffer != NULL)
usb_buffer_free(gspca_dev->dev,
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);
usb_free_coherent(gspca_dev->dev,
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);
usb_free_urb(urb);
}
}
@ -760,13 +760,13 @@ static int create_urbs(struct gspca_dev *gspca_dev,
return -ENOMEM;
}
gspca_dev->urb[n] = urb;
urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
bsize,
GFP_KERNEL,
&urb->transfer_dma);
if (urb->transfer_buffer == NULL) {
err("usb_buffer_alloc failed");
err("usb_alloc_coherent failed");
return -ENOMEM;
}
urb->dev = gspca_dev->dev;

View File

@ -92,8 +92,8 @@ static int hdpvr_free_queue(struct list_head *q)
buf = list_entry(p, struct hdpvr_buffer, buff_list);
urb = buf->urb;
usb_buffer_free(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
usb_free_coherent(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
usb_free_urb(urb);
tmp = p->next;
list_del(p);
@ -143,8 +143,8 @@ int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count)
}
buf->urb = urb;
mem = usb_buffer_alloc(dev->udev, dev->bulk_in_size, GFP_KERNEL,
&urb->transfer_dma);
mem = usb_alloc_coherent(dev->udev, dev->bulk_in_size, GFP_KERNEL,
&urb->transfer_dma);
if (!mem) {
v4l2_err(&dev->v4l2_dev,
"cannot allocate usb transfer buffer\n");

View File

@ -454,8 +454,8 @@ static int poseidon_probe(struct usb_interface *interface,
device_init_wakeup(&udev->dev, 1);
#ifdef CONFIG_PM
pd->udev->autosuspend_disabled = 0;
pd->udev->autosuspend_delay = HZ * PM_SUSPEND_DELAY;
usb_enable_autosuspend(pd->udev);
if (in_hibernation(pd)) {
INIT_WORK(&pd->pm_work, hibernation_resume);

View File

@ -478,10 +478,10 @@ static int prepare_iso_urb(struct video_data *video)
goto out;
video->urb_array[i] = urb;
mem = usb_buffer_alloc(udev,
ISO_PKT_SIZE * PK_PER_URB,
GFP_KERNEL,
&urb->transfer_dma);
mem = usb_alloc_coherent(udev,
ISO_PKT_SIZE * PK_PER_URB,
GFP_KERNEL,
&urb->transfer_dma);
urb->complete = urb_complete_iso; /* handler */
urb->dev = udev;
@ -521,8 +521,8 @@ int alloc_bulk_urbs_generic(struct urb **urb_array, int num,
if (urb == NULL)
return i;
mem = usb_buffer_alloc(udev, buf_size, gfp_flags,
&urb->transfer_dma);
mem = usb_alloc_coherent(udev, buf_size, gfp_flags,
&urb->transfer_dma);
if (mem == NULL)
return i;
@ -542,7 +542,7 @@ void free_all_urb_generic(struct urb **urb_array, int num)
for (i = 0; i < num; i++) {
urb = urb_array[i];
if (urb) {
usb_buffer_free(urb->dev,
usb_free_coherent(urb->dev,
urb->transfer_buffer_length,
urb->transfer_buffer,
urb->transfer_dma);

View File

@ -2493,10 +2493,10 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
}
usbvision->sbuf[bufIdx].urb = urb;
usbvision->sbuf[bufIdx].data =
usb_buffer_alloc(usbvision->dev,
sb_size,
GFP_KERNEL,
&urb->transfer_dma);
usb_alloc_coherent(usbvision->dev,
sb_size,
GFP_KERNEL,
&urb->transfer_dma);
urb->dev = dev;
urb->context = usbvision;
urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp);
@ -2552,10 +2552,10 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
usb_kill_urb(usbvision->sbuf[bufIdx].urb);
if (usbvision->sbuf[bufIdx].data){
usb_buffer_free(usbvision->dev,
sb_size,
usbvision->sbuf[bufIdx].data,
usbvision->sbuf[bufIdx].urb->transfer_dma);
usb_free_coherent(usbvision->dev,
sb_size,
usbvision->sbuf[bufIdx].data,
usbvision->sbuf[bufIdx].urb->transfer_dma);
}
usb_free_urb(usbvision->sbuf[bufIdx].urb);
usbvision->sbuf[bufIdx].urb = NULL;

View File

@ -739,7 +739,7 @@ static void uvc_free_urb_buffers(struct uvc_streaming *stream)
for (i = 0; i < UVC_URBS; ++i) {
if (stream->urb_buffer[i]) {
usb_buffer_free(stream->dev->udev, stream->urb_size,
usb_free_coherent(stream->dev->udev, stream->urb_size,
stream->urb_buffer[i], stream->urb_dma[i]);
stream->urb_buffer[i] = NULL;
}
@ -780,7 +780,7 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream,
for (; npackets > 1; npackets /= 2) {
for (i = 0; i < UVC_URBS; ++i) {
stream->urb_size = psize * npackets;
stream->urb_buffer[i] = usb_buffer_alloc(
stream->urb_buffer[i] = usb_alloc_coherent(
stream->dev->udev, stream->urb_size,
gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]);
if (!stream->urb_buffer[i]) {

View File

@ -512,8 +512,8 @@ static void ems_usb_write_bulk_callback(struct urb *urb)
netdev = dev->netdev;
/* free up our allocated buffer */
usb_buffer_free(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
usb_free_coherent(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
atomic_dec(&dev->active_tx_urbs);
@ -610,8 +610,8 @@ static int ems_usb_start(struct ems_usb *dev)
return -ENOMEM;
}
buf = usb_buffer_alloc(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
&urb->transfer_dma);
buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
&urb->transfer_dma);
if (!buf) {
dev_err(netdev->dev.parent,
"No memory left for USB buffer\n");
@ -631,8 +631,8 @@ static int ems_usb_start(struct ems_usb *dev)
netif_device_detach(dev->netdev);
usb_unanchor_urb(urb);
usb_buffer_free(dev->udev, RX_BUFFER_SIZE, buf,
urb->transfer_dma);
usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
urb->transfer_dma);
break;
}
@ -773,7 +773,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
goto nomem;
}
buf = usb_buffer_alloc(dev->udev, size, GFP_ATOMIC, &urb->transfer_dma);
buf = usb_alloc_coherent(dev->udev, size, GFP_ATOMIC, &urb->transfer_dma);
if (!buf) {
dev_err(netdev->dev.parent, "No memory left for USB buffer\n");
usb_free_urb(urb);
@ -816,7 +816,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
*/
if (!context) {
usb_unanchor_urb(urb);
usb_buffer_free(dev->udev, size, buf, urb->transfer_dma);
usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
dev_warn(netdev->dev.parent, "couldn't find free context\n");
@ -841,7 +841,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
can_free_echo_skb(netdev, context->echo_index);
usb_unanchor_urb(urb);
usb_buffer_free(dev->udev, size, buf, urb->transfer_dma);
usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
dev_kfree_skb(skb);
atomic_dec(&dev->active_tx_urbs);

View File

@ -128,17 +128,13 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone)
if (rx_urb == NULL)
goto free_tx_urb;
tx_buf = usb_buffer_alloc(iphone->udev,
IPHETH_BUF_SIZE,
GFP_KERNEL,
&tx_urb->transfer_dma);
tx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE,
GFP_KERNEL, &tx_urb->transfer_dma);
if (tx_buf == NULL)
goto free_rx_urb;
rx_buf = usb_buffer_alloc(iphone->udev,
IPHETH_BUF_SIZE,
GFP_KERNEL,
&rx_urb->transfer_dma);
rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE,
GFP_KERNEL, &rx_urb->transfer_dma);
if (rx_buf == NULL)
goto free_tx_buf;
@ -150,8 +146,8 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone)
return 0;
free_tx_buf:
usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, tx_buf,
tx_urb->transfer_dma);
usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, tx_buf,
tx_urb->transfer_dma);
free_rx_urb:
usb_free_urb(rx_urb);
free_tx_urb:
@ -162,10 +158,10 @@ error_nomem:
static void ipheth_free_urbs(struct ipheth_device *iphone)
{
usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, iphone->rx_buf,
iphone->rx_urb->transfer_dma);
usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf,
iphone->tx_urb->transfer_dma);
usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->rx_buf,
iphone->rx_urb->transfer_dma);
usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf,
iphone->tx_urb->transfer_dma);
usb_free_urb(iphone->rx_urb);
usb_free_urb(iphone->tx_urb);
}

View File

@ -1155,13 +1155,13 @@ err_fw:
if (!kaweth->irq_urb)
goto err_tx_and_rx;
kaweth->intbuffer = usb_buffer_alloc( kaweth->dev,
kaweth->intbuffer = usb_alloc_coherent( kaweth->dev,
INTBUFFERSIZE,
GFP_KERNEL,
&kaweth->intbufferhandle);
if (!kaweth->intbuffer)
goto err_tx_and_rx_and_irq;
kaweth->rx_buf = usb_buffer_alloc( kaweth->dev,
kaweth->rx_buf = usb_alloc_coherent( kaweth->dev,
KAWETH_BUF_SIZE,
GFP_KERNEL,
&kaweth->rxbufferhandle);
@ -1202,9 +1202,9 @@ err_fw:
err_intfdata:
usb_set_intfdata(intf, NULL);
usb_buffer_free(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle);
usb_free_coherent(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle);
err_all_but_rxbuf:
usb_buffer_free(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle);
usb_free_coherent(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle);
err_tx_and_rx_and_irq:
usb_free_urb(kaweth->irq_urb);
err_tx_and_rx:
@ -1241,8 +1241,8 @@ static void kaweth_disconnect(struct usb_interface *intf)
usb_free_urb(kaweth->tx_urb);
usb_free_urb(kaweth->irq_urb);
usb_buffer_free(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle);
usb_buffer_free(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle);
usb_free_coherent(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle);
usb_free_coherent(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle);
free_netdev(netdev);
}

View File

@ -514,7 +514,7 @@ int i2400mu_probe(struct usb_interface *iface,
iface->needs_remote_wakeup = 1; /* autosuspend (15s delay) */
device_init_wakeup(dev, 1);
usb_dev->autosuspend_delay = 15 * HZ;
usb_dev->autosuspend_disabled = 0;
usb_enable_autosuspend(usb_dev);
#endif
result = i2400m_setup(i2400m, I2400M_BRI_MAC_REINIT);

View File

@ -215,7 +215,7 @@ resubmit:
return;
free:
usb_buffer_free(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma);
usb_free_coherent(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma);
}
static void ar9170_usb_rx_completed(struct urb *urb)
@ -296,7 +296,7 @@ static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru)
if (!urb)
goto out;
ibuf = usb_buffer_alloc(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma);
ibuf = usb_alloc_coherent(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma);
if (!ibuf)
goto out;
@ -309,8 +309,8 @@ static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru)
err = usb_submit_urb(urb, GFP_KERNEL);
if (err) {
usb_unanchor_urb(urb);
usb_buffer_free(aru->udev, 64, urb->transfer_buffer,
urb->transfer_dma);
usb_free_coherent(aru->udev, 64, urb->transfer_buffer,
urb->transfer_dma);
}
out:

View File

@ -664,15 +664,15 @@ static struct urb *alloc_rx_urb(struct zd_usb *usb)
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
return NULL;
buffer = usb_buffer_alloc(udev, USB_MAX_RX_SIZE, GFP_KERNEL,
&urb->transfer_dma);
buffer = usb_alloc_coherent(udev, USB_MAX_RX_SIZE, GFP_KERNEL,
&urb->transfer_dma);
if (!buffer) {
usb_free_urb(urb);
return NULL;
}
usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, EP_DATA_IN),
buffer, USB_MAX_RX_SIZE,
buffer, USB_MAX_RX_SIZE,
rx_urb_complete, usb);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@ -683,8 +683,8 @@ static void free_rx_urb(struct urb *urb)
{
if (!urb)
return;
usb_buffer_free(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
usb_free_coherent(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
usb_free_urb(urb);
}

View File

@ -81,8 +81,8 @@ extern u8 EpToQueue[6];
#define RT28XX_PUT_DEVICE usb_put_dev
#define RTUSB_ALLOC_URB(iso) usb_alloc_urb(iso, GFP_ATOMIC)
#define RTUSB_SUBMIT_URB(pUrb) usb_submit_urb(pUrb, GFP_ATOMIC)
#define RTUSB_URB_ALLOC_BUFFER(pUsb_Dev, BufSize, pDma_addr) usb_buffer_alloc(pUsb_Dev, BufSize, GFP_ATOMIC, pDma_addr)
#define RTUSB_URB_FREE_BUFFER(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) usb_buffer_free(pUsb_Dev, BufSize, pTransferBuf, Dma_addr)
#define RTUSB_URB_ALLOC_BUFFER(pUsb_Dev, BufSize, pDma_addr) usb_alloc_coherent(pUsb_Dev, BufSize, GFP_ATOMIC, pDma_addr)
#define RTUSB_URB_FREE_BUFFER(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) usb_free_coherent(pUsb_Dev, BufSize, pTransferBuf, Dma_addr)
#define RTUSB_FREE_URB(pUrb) usb_free_urb(pUrb)

View File

@ -1508,8 +1508,8 @@ static void dlfb_free_urb_list(struct dlfb_data *dev)
urb = unode->urb;
/* Free each separately allocated piece */
usb_buffer_free(urb->dev, dev->urbs.size,
urb->transfer_buffer, urb->transfer_dma);
usb_free_coherent(urb->dev, dev->urbs.size,
urb->transfer_buffer, urb->transfer_dma);
usb_free_urb(urb);
kfree(node);
}
@ -1543,8 +1543,8 @@ static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
}
unode->urb = urb;
buf = usb_buffer_alloc(dev->udev, MAX_TRANSFER, GFP_KERNEL,
&urb->transfer_dma);
buf = usb_alloc_coherent(dev->udev, MAX_TRANSFER, GFP_KERNEL,
&urb->transfer_dma);
if (!buf) {
kfree(unode);
usb_free_urb(urb);

View File

@ -21,7 +21,7 @@
#include "usbip_common.h"
#include "stub.h"
#include "../../usb/core/hcd.h"
#include <linux/usb/hcd.h>
static int is_clear_halt_cmd(struct urb *urb)

View File

@ -562,7 +562,7 @@ EXPORT_SYMBOL_GPL(sockfd_to_socket);
/* there may be more cases to tweak the flags. */
static unsigned int tweak_transfer_flags(unsigned int flags)
{
flags &= ~(URB_NO_TRANSFER_DMA_MAP|URB_NO_SETUP_DMA_MAP);
flags &= ~URB_NO_TRANSFER_DMA_MAP;
return flags;
}

View File

@ -18,7 +18,7 @@
*/
#include <linux/platform_device.h>
#include "../../usb/core/hcd.h"
#include <linux/usb/hcd.h>
struct vhci_device {

View File

@ -94,19 +94,19 @@
} while (0)
#define uea_enters(usb_dev) \
uea_vdbg(usb_dev, "entering %s\n", __func__)
uea_vdbg(usb_dev, "entering %s\n" , __func__)
#define uea_leaves(usb_dev) \
uea_vdbg(usb_dev, "leaving %s\n", __func__)
uea_vdbg(usb_dev, "leaving %s\n" , __func__)
#define uea_err(usb_dev, format,args...) \
dev_err(&(usb_dev)->dev ,"[UEAGLE-ATM] " format , ##args)
#define uea_err(usb_dev, format, args...) \
dev_err(&(usb_dev)->dev , "[UEAGLE-ATM] " format , ##args)
#define uea_warn(usb_dev, format,args...) \
dev_warn(&(usb_dev)->dev ,"[Ueagle-atm] " format, ##args)
#define uea_warn(usb_dev, format, args...) \
dev_warn(&(usb_dev)->dev , "[Ueagle-atm] " format, ##args)
#define uea_info(usb_dev, format,args...) \
dev_info(&(usb_dev)->dev ,"[ueagle-atm] " format, ##args)
#define uea_info(usb_dev, format, args...) \
dev_info(&(usb_dev)->dev , "[ueagle-atm] " format, ##args)
struct intr_pkt;
@ -289,7 +289,7 @@ enum {
#define IS_ISDN(x) \
((x)->annex & ANNEXB)
#define INS_TO_USBDEV(ins) ins->usb_dev
#define INS_TO_USBDEV(ins) (ins->usb_dev)
#define GET_STATUS(data) \
((data >> 8) & 0xf)
@ -304,7 +304,7 @@ enum {
* The FW_GET_BYTE() macro is provided only for consistency.
*/
#define FW_GET_BYTE(p) *((__u8 *) (p))
#define FW_GET_BYTE(p) (*((__u8 *) (p)))
#define FW_DIR "ueagle-atm/"
#define UEA_FW_NAME_MAX 30
@ -315,7 +315,7 @@ enum {
#define ACK_TIMEOUT msecs_to_jiffies(3000)
#define UEA_INTR_IFACE_NO 0
#define UEA_INTR_IFACE_NO 0
#define UEA_US_IFACE_NO 1
#define UEA_DS_IFACE_NO 2
@ -326,9 +326,9 @@ enum {
#define UEA_INTR_PIPE 0x04
#define UEA_ISO_DATA_PIPE 0x08
#define UEA_E1_SET_BLOCK 0x0001
#define UEA_E1_SET_BLOCK 0x0001
#define UEA_E4_SET_BLOCK 0x002c
#define UEA_SET_MODE 0x0003
#define UEA_SET_MODE 0x0003
#define UEA_SET_2183_DATA 0x0004
#define UEA_SET_TIMEOUT 0x0011
@ -366,7 +366,7 @@ struct l1_code {
u8 string_header[E4_L1_STRING_HEADER];
u8 page_number_to_block_index[E4_MAX_PAGE_NUMBER];
struct block_index page_header[E4_NO_SWAPPAGE_HEADERS];
u8 code [0];
u8 code[0];
} __attribute__ ((packed));
/* structures describing a block within a DSP page */
@ -428,7 +428,8 @@ struct block_info_e4 {
#define E4_MODEMREADY 0x1
#define E1_MAKEFUNCTION(t, s) (((t) & 0xf) << 4 | ((s) & 0xf))
#define E4_MAKEFUNCTION(t, st, s) (((t) & 0xf) << 8 | ((st) & 0xf) << 4 | ((s) & 0xf))
#define E4_MAKEFUNCTION(t, st, s) (((t) & 0xf) << 8 | \
((st) & 0xf) << 4 | ((s) & 0xf))
#define E1_MAKESA(a, b, c, d) \
(((c) & 0xff) << 24 | \
@ -473,7 +474,7 @@ struct cmv_e4 {
__be16 wFunction;
__be16 wOffset;
__be16 wAddress;
__be32 dwData [6];
__be32 dwData[6];
} __attribute__ ((packed));
/* structures representing swap information */
@ -534,11 +535,13 @@ struct intr_pkt {
static struct usb_driver uea_driver;
static DEFINE_MUTEX(uea_mutex);
static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III", "Eagle IV"};
static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III",
"Eagle IV"};
static int modem_index;
static unsigned int debug;
static unsigned int altsetting[NB_MODEM] = {[0 ... (NB_MODEM - 1)] = FASTEST_ISO_INTF};
static unsigned int altsetting[NB_MODEM] = {
[0 ... (NB_MODEM - 1)] = FASTEST_ISO_INTF};
static int sync_wait[NB_MODEM];
static char *cmv_file[NB_MODEM];
static int annex[NB_MODEM];
@ -555,7 +558,7 @@ MODULE_PARM_DESC(cmv_file,
"file name with configuration and management variables");
module_param_array(annex, uint, NULL, 0644);
MODULE_PARM_DESC(annex,
"manually set annex a/b (0=auto, 1=annex a, 2=annex b)");
"manually set annex a/b (0=auto, 1=annex a, 2=annex b)");
#define uea_wait(sc, cond, timeo) \
({ \
@ -602,7 +605,8 @@ static int uea_send_modem_cmd(struct usb_device *usb,
return (ret == size) ? 0 : -EIO;
}
static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *context)
static void uea_upload_pre_firmware(const struct firmware *fw_entry,
void *context)
{
struct usb_device *usb = context;
const u8 *pfw;
@ -707,7 +711,8 @@ static int uea_load_firmware(struct usb_device *usb, unsigned int ver)
}
ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev,
GFP_KERNEL, usb, uea_upload_pre_firmware);
GFP_KERNEL, usb,
uea_upload_pre_firmware);
if (ret)
uea_err(usb, "firmware %s is not available\n", fw_name);
else
@ -876,7 +881,7 @@ static int request_dsp(struct uea_softc *sc)
if (ret < 0) {
uea_err(INS_TO_USBDEV(sc),
"requesting firmware %s failed with error %d\n",
dsp_name, ret);
dsp_name, ret);
return ret;
}
@ -994,14 +999,17 @@ static void __uea_load_page_e4(struct uea_softc *sc, u8 pageno, int boot)
blockidx = &p->page_header[blockno];
blocksize = E4_PAGE_BYTES(blockidx->PageSize);
blockoffset = sc->dsp_firm->data + le32_to_cpu(blockidx->PageOffset);
blockoffset = sc->dsp_firm->data + le32_to_cpu(
blockidx->PageOffset);
bi.dwSize = cpu_to_be32(blocksize);
bi.dwAddress = cpu_to_be32(le32_to_cpu(blockidx->PageAddress));
uea_dbg(INS_TO_USBDEV(sc),
"sending block %u for DSP page %u size %u address %x\n",
blockno, pageno, blocksize, le32_to_cpu(blockidx->PageAddress));
"sending block %u for DSP page "
"%u size %u address %x\n",
blockno, pageno, blocksize,
le32_to_cpu(blockidx->PageAddress));
/* send block info through the IDMA pipe */
if (uea_idma_write(sc, &bi, E4_BLOCK_INFO_SIZE))
@ -1042,7 +1050,8 @@ static void uea_load_page_e4(struct work_struct *work)
p = (struct l1_code *) sc->dsp_firm->data;
if (pageno >= le16_to_cpu(p->page_header[0].PageNumber)) {
uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno);
uea_err(INS_TO_USBDEV(sc), "invalid DSP "
"page %u requested\n", pageno);
return;
}
@ -1059,7 +1068,7 @@ static void uea_load_page_e4(struct work_struct *work)
__uea_load_page_e4(sc, i, 1);
}
uea_dbg(INS_TO_USBDEV(sc),"sending start bi\n");
uea_dbg(INS_TO_USBDEV(sc) , "sending start bi\n");
bi.wHdr = cpu_to_be16(UEA_BIHDR);
bi.bBootPage = 0;
@ -1139,8 +1148,10 @@ static int uea_cmv_e1(struct uea_softc *sc,
uea_enters(INS_TO_USBDEV(sc));
uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Address : %c%c%c%c, "
"offset : 0x%04x, data : 0x%08x\n",
E1_FUNCTION_TYPE(function), E1_FUNCTION_SUBTYPE(function),
E1_GETSA1(address), E1_GETSA2(address), E1_GETSA3(address),
E1_FUNCTION_TYPE(function),
E1_FUNCTION_SUBTYPE(function),
E1_GETSA1(address), E1_GETSA2(address),
E1_GETSA3(address),
E1_GETSA4(address), offset, data);
/* we send a request, but we expect a reply */
@ -1157,7 +1168,8 @@ static int uea_cmv_e1(struct uea_softc *sc,
cmv.wOffsetAddress = cpu_to_le16(offset);
put_unaligned_le32(data >> 16 | data << 16, &cmv.dwData);
ret = uea_request(sc, UEA_E1_SET_BLOCK, UEA_MPTX_START, sizeof(cmv), &cmv);
ret = uea_request(sc, UEA_E1_SET_BLOCK, UEA_MPTX_START,
sizeof(cmv), &cmv);
if (ret < 0)
return ret;
ret = wait_cmv_ack(sc);
@ -1191,7 +1203,8 @@ static int uea_cmv_e4(struct uea_softc *sc,
cmv.wOffset = cpu_to_be16(offset);
cmv.dwData[0] = cpu_to_be32(data);
ret = uea_request(sc, UEA_E4_SET_BLOCK, UEA_MPTX_START, sizeof(cmv), &cmv);
ret = uea_request(sc, UEA_E4_SET_BLOCK, UEA_MPTX_START,
sizeof(cmv), &cmv);
if (ret < 0)
return ret;
ret = wait_cmv_ack(sc);
@ -1208,7 +1221,7 @@ static inline int uea_read_cmv_e1(struct uea_softc *sc,
uea_err(INS_TO_USBDEV(sc),
"reading cmv failed with error %d\n", ret);
else
*data = sc->data;
*data = sc->data;
return ret;
}
@ -1216,13 +1229,14 @@ static inline int uea_read_cmv_e1(struct uea_softc *sc,
static inline int uea_read_cmv_e4(struct uea_softc *sc,
u8 size, u16 group, u16 address, u16 offset, u32 *data)
{
int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS, E4_REQUESTREAD, size),
int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS,
E4_REQUESTREAD, size),
group, address, offset, 0);
if (ret < 0)
uea_err(INS_TO_USBDEV(sc),
"reading cmv failed with error %d\n", ret);
else {
*data = sc->data;
*data = sc->data;
/* size is in 16-bit word quantities */
if (size > 2)
*(data + 1) = sc->data1;
@ -1245,7 +1259,8 @@ static inline int uea_write_cmv_e1(struct uea_softc *sc,
static inline int uea_write_cmv_e4(struct uea_softc *sc,
u8 size, u16 group, u16 address, u16 offset, u32 data)
{
int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS, E4_REQUESTWRITE, size),
int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS,
E4_REQUESTWRITE, size),
group, address, offset, data);
if (ret < 0)
uea_err(INS_TO_USBDEV(sc),
@ -1442,27 +1457,29 @@ static int uea_stat_e4(struct uea_softc *sc)
return ret;
switch (sc->stats.phy.state) {
case 0x0: /* not yet synchronized */
case 0x1:
case 0x3:
case 0x4:
uea_dbg(INS_TO_USBDEV(sc), "modem not yet synchronized\n");
return 0;
case 0x5: /* initialization */
case 0x6:
case 0x9:
case 0xa:
uea_dbg(INS_TO_USBDEV(sc), "modem initializing\n");
return 0;
case 0x2: /* fail ... */
uea_info(INS_TO_USBDEV(sc), "modem synchronization failed"
" (may be try other cmv/dsp)\n");
return -EAGAIN;
case 0x7: /* operational */
break;
default:
uea_warn(INS_TO_USBDEV(sc), "unknown state: %x\n", sc->stats.phy.state);
return 0;
case 0x0: /* not yet synchronized */
case 0x1:
case 0x3:
case 0x4:
uea_dbg(INS_TO_USBDEV(sc), "modem not yet "
"synchronized\n");
return 0;
case 0x5: /* initialization */
case 0x6:
case 0x9:
case 0xa:
uea_dbg(INS_TO_USBDEV(sc), "modem initializing\n");
return 0;
case 0x2: /* fail ... */
uea_info(INS_TO_USBDEV(sc), "modem synchronization "
"failed (may be try other cmv/dsp)\n");
return -EAGAIN;
case 0x7: /* operational */
break;
default:
uea_warn(INS_TO_USBDEV(sc), "unknown state: %x\n",
sc->stats.phy.state);
return 0;
}
if (data != 7) {
@ -1502,9 +1519,9 @@ static int uea_stat_e4(struct uea_softc *sc)
if (sc->stats.phy.flags) {
uea_dbg(INS_TO_USBDEV(sc), "Stat flag = 0x%x\n",
sc->stats.phy.flags);
if (sc->stats.phy.flags & 1) //delineation LOSS
if (sc->stats.phy.flags & 1) /* delineation LOSS */
return -EAGAIN;
if (sc->stats.phy.flags & 0x4000) //Reset Flag
if (sc->stats.phy.flags & 0x4000) /* Reset Flag */
return -EAGAIN;
return 0;
}
@ -1618,7 +1635,8 @@ static int request_cmvs(struct uea_softc *sc,
if (ret < 0) {
/* if caller can handle old version, try to provide it */
if (*ver == 1) {
uea_warn(INS_TO_USBDEV(sc), "requesting firmware %s failed, "
uea_warn(INS_TO_USBDEV(sc), "requesting "
"firmware %s failed, "
"try to get older cmvs\n", cmv_name);
return request_cmvs_old(sc, cmvs, fw);
}
@ -1632,8 +1650,8 @@ static int request_cmvs(struct uea_softc *sc,
data = (u8 *) (*fw)->data;
if (size < 4 || strncmp(data, "cmv2", 4) != 0) {
if (*ver == 1) {
uea_warn(INS_TO_USBDEV(sc), "firmware %s is corrupted, "
"try to get older cmvs\n", cmv_name);
uea_warn(INS_TO_USBDEV(sc), "firmware %s is corrupted,"
" try to get older cmvs\n", cmv_name);
release_firmware(*fw);
return request_cmvs_old(sc, cmvs, fw);
}
@ -1670,7 +1688,7 @@ static int uea_send_cmvs_e1(struct uea_softc *sc)
int i, ret, len;
void *cmvs_ptr;
const struct firmware *cmvs_fw;
int ver = 1; // we can handle v1 cmv firmware version;
int ver = 1; /* we can handle v1 cmv firmware version; */
/* Enter in R-IDLE (cmv) until instructed otherwise */
ret = uea_write_cmv_e1(sc, E1_SA_CNTL, 0, 1);
@ -1685,7 +1703,7 @@ static int uea_send_cmvs_e1(struct uea_softc *sc)
sc->stats.phy.firmid);
/* get options */
ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver);
ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver);
if (ret < 0)
return ret;
@ -1697,9 +1715,10 @@ static int uea_send_cmvs_e1(struct uea_softc *sc)
"please update your firmware\n");
for (i = 0; i < len; i++) {
ret = uea_write_cmv_e1(sc, get_unaligned_le32(&cmvs_v1[i].address),
get_unaligned_le16(&cmvs_v1[i].offset),
get_unaligned_le32(&cmvs_v1[i].data));
ret = uea_write_cmv_e1(sc,
get_unaligned_le32(&cmvs_v1[i].address),
get_unaligned_le16(&cmvs_v1[i].offset),
get_unaligned_le32(&cmvs_v1[i].data));
if (ret < 0)
goto out;
}
@ -1707,9 +1726,10 @@ static int uea_send_cmvs_e1(struct uea_softc *sc)
struct uea_cmvs_v2 *cmvs_v2 = cmvs_ptr;
for (i = 0; i < len; i++) {
ret = uea_write_cmv_e1(sc, get_unaligned_le32(&cmvs_v2[i].address),
(u16) get_unaligned_le32(&cmvs_v2[i].offset),
get_unaligned_le32(&cmvs_v2[i].data));
ret = uea_write_cmv_e1(sc,
get_unaligned_le32(&cmvs_v2[i].address),
(u16) get_unaligned_le32(&cmvs_v2[i].offset),
get_unaligned_le32(&cmvs_v2[i].data));
if (ret < 0)
goto out;
}
@ -1722,7 +1742,8 @@ static int uea_send_cmvs_e1(struct uea_softc *sc)
/* Enter in R-ACT-REQ */
ret = uea_write_cmv_e1(sc, E1_SA_CNTL, 0, 2);
uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n");
uea_info(INS_TO_USBDEV(sc), "modem started, waiting synchronization...\n");
uea_info(INS_TO_USBDEV(sc), "modem started, waiting "
"synchronization...\n");
out:
release_firmware(cmvs_fw);
return ret;
@ -1733,7 +1754,7 @@ static int uea_send_cmvs_e4(struct uea_softc *sc)
int i, ret, len;
void *cmvs_ptr;
const struct firmware *cmvs_fw;
int ver = 2; // we can only handle v2 cmv firmware version;
int ver = 2; /* we can only handle v2 cmv firmware version; */
/* Enter in R-IDLE (cmv) until instructed otherwise */
ret = uea_write_cmv_e4(sc, 1, E4_SA_CNTL, 0, 0, 1);
@ -1750,7 +1771,7 @@ static int uea_send_cmvs_e4(struct uea_softc *sc)
/* get options */
ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver);
ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver);
if (ret < 0)
return ret;
@ -1760,10 +1781,10 @@ static int uea_send_cmvs_e4(struct uea_softc *sc)
for (i = 0; i < len; i++) {
ret = uea_write_cmv_e4(sc, 1,
get_unaligned_le32(&cmvs_v2[i].group),
get_unaligned_le32(&cmvs_v2[i].address),
get_unaligned_le32(&cmvs_v2[i].offset),
get_unaligned_le32(&cmvs_v2[i].data));
get_unaligned_le32(&cmvs_v2[i].group),
get_unaligned_le32(&cmvs_v2[i].address),
get_unaligned_le32(&cmvs_v2[i].offset),
get_unaligned_le32(&cmvs_v2[i].data));
if (ret < 0)
goto out;
}
@ -1776,7 +1797,8 @@ static int uea_send_cmvs_e4(struct uea_softc *sc)
/* Enter in R-ACT-REQ */
ret = uea_write_cmv_e4(sc, 1, E4_SA_CNTL, 0, 0, 2);
uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n");
uea_info(INS_TO_USBDEV(sc), "modem started, waiting synchronization...\n");
uea_info(INS_TO_USBDEV(sc), "modem started, waiting "
"synchronization...\n");
out:
release_firmware(cmvs_fw);
return ret;
@ -1812,7 +1834,7 @@ static int uea_start_reset(struct uea_softc *sc)
uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL);
uea_request(sc, UEA_SET_MODE, UEA_BOOT_IDMA, 0, NULL);
/* enter reset mode */
/* enter reset mode */
uea_request(sc, UEA_SET_MODE, UEA_START_RESET, 0, NULL);
/* original driver use 200ms, but windows driver use 100ms */
@ -1824,7 +1846,7 @@ static int uea_start_reset(struct uea_softc *sc)
uea_request(sc, UEA_SET_MODE, UEA_END_RESET, 0, NULL);
if (UEA_CHIP_VERSION(sc) != EAGLE_IV) {
/* clear tx and rx mailboxes */
/* clear tx and rx mailboxes */
uea_request(sc, UEA_SET_2183_DATA, UEA_MPTX_MAILBOX, 2, &zero);
uea_request(sc, UEA_SET_2183_DATA, UEA_MPRX_MAILBOX, 2, &zero);
uea_request(sc, UEA_SET_2183_DATA, UEA_SWAP_MAILBOX, 2, &zero);
@ -1835,9 +1857,11 @@ static int uea_start_reset(struct uea_softc *sc)
return ret;
if (UEA_CHIP_VERSION(sc) == EAGLE_IV)
sc->cmv_dsc.e4.function = E4_MAKEFUNCTION(E4_ADSLDIRECTIVE, E4_MODEMREADY, 1);
sc->cmv_dsc.e4.function = E4_MAKEFUNCTION(E4_ADSLDIRECTIVE,
E4_MODEMREADY, 1);
else
sc->cmv_dsc.e1.function = E1_MAKEFUNCTION(E1_ADSLDIRECTIVE, E1_MODEMREADY);
sc->cmv_dsc.e1.function = E1_MAKEFUNCTION(E1_ADSLDIRECTIVE,
E1_MODEMREADY);
/* demask interrupt */
sc->booting = 0;
@ -1937,7 +1961,8 @@ static int load_XILINX_firmware(struct uea_softc *sc)
value = 0;
ret = uea_send_modem_cmd(sc->usb_dev, 0xe, 1, &value);
if (ret < 0)
uea_err(sc->usb_dev, "elsa de-assert failed with error %d\n", ret);
uea_err(sc->usb_dev, "elsa de-assert failed with error"
" %d\n", ret);
err1:
release_firmware(fw_entry);
@ -1966,13 +1991,15 @@ static void uea_dispatch_cmv_e1(struct uea_softc *sc, struct intr_pkt *intr)
if (UEA_CHIP_VERSION(sc) == ADI930
&& cmv->bFunction == E1_MAKEFUNCTION(2, 2)) {
cmv->wIndex = cpu_to_le16(dsc->idx);
put_unaligned_le32(dsc->address, &cmv->dwSymbolicAddress);
put_unaligned_le32(dsc->address,
&cmv->dwSymbolicAddress);
cmv->wOffsetAddress = cpu_to_le16(dsc->offset);
} else
goto bad2;
}
if (cmv->bFunction == E1_MAKEFUNCTION(E1_ADSLDIRECTIVE, E1_MODEMREADY)) {
if (cmv->bFunction == E1_MAKEFUNCTION(E1_ADSLDIRECTIVE,
E1_MODEMREADY)) {
wake_up_cmv_ack(sc);
uea_leaves(INS_TO_USBDEV(sc));
return;
@ -2021,7 +2048,8 @@ static void uea_dispatch_cmv_e4(struct uea_softc *sc, struct intr_pkt *intr)
if (be16_to_cpu(cmv->wFunction) != dsc->function)
goto bad2;
if (be16_to_cpu(cmv->wFunction) == E4_MAKEFUNCTION(E4_ADSLDIRECTIVE, E4_MODEMREADY, 1)) {
if (be16_to_cpu(cmv->wFunction) == E4_MAKEFUNCTION(E4_ADSLDIRECTIVE,
E4_MODEMREADY, 1)) {
wake_up_cmv_ack(sc);
uea_leaves(INS_TO_USBDEV(sc));
return;
@ -2048,14 +2076,16 @@ bad2:
return;
}
static void uea_schedule_load_page_e1(struct uea_softc *sc, struct intr_pkt *intr)
static void uea_schedule_load_page_e1(struct uea_softc *sc,
struct intr_pkt *intr)
{
sc->pageno = intr->e1_bSwapPageNo;
sc->ovl = intr->e1_bOvl >> 4 | intr->e1_bOvl << 4;
queue_work(sc->work_q, &sc->task);
}
static void uea_schedule_load_page_e4(struct uea_softc *sc, struct intr_pkt *intr)
static void uea_schedule_load_page_e4(struct uea_softc *sc,
struct intr_pkt *intr)
{
sc->pageno = intr->e4_bSwapPageNo;
queue_work(sc->work_q, &sc->task);
@ -2263,8 +2293,8 @@ out:
static DEVICE_ATTR(stat_status, S_IWUGO | S_IRUGO, read_status, reboot);
static ssize_t read_human_status(struct device *dev, struct device_attribute *attr,
char *buf)
static ssize_t read_human_status(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret = -ENODEV;
int modem_state;
@ -2289,7 +2319,7 @@ static ssize_t read_human_status(struct device *dev, struct device_attribute *at
case 0xa:
modem_state = 1;
break;
case 0x7: /* operational */
case 0x7: /* operational */
modem_state = 2;
break;
case 0x2: /* fail ... */
@ -2324,7 +2354,8 @@ out:
return ret;
}
static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO, read_human_status, NULL);
static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO,
read_human_status, NULL);
static ssize_t read_delin(struct device *dev, struct device_attribute *attr,
char *buf)
@ -2358,25 +2389,25 @@ out:
static DEVICE_ATTR(stat_delin, S_IWUGO | S_IRUGO, read_delin, NULL);
#define UEA_ATTR(name, reset) \
#define UEA_ATTR(name, reset) \
\
static ssize_t read_##name(struct device *dev, \
static ssize_t read_##name(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
int ret = -ENODEV; \
struct uea_softc *sc; \
\
mutex_lock(&uea_mutex); \
{ \
int ret = -ENODEV; \
struct uea_softc *sc; \
\
mutex_lock(&uea_mutex); \
sc = dev_to_uea(dev); \
if (!sc) \
goto out; \
if (!sc) \
goto out; \
ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.name); \
if (reset) \
sc->stats.phy.name = 0; \
out: \
mutex_unlock(&uea_mutex); \
return ret; \
} \
out: \
mutex_unlock(&uea_mutex); \
return ret; \
} \
\
static DEVICE_ATTR(stat_##name, S_IRUGO, read_##name, NULL)
@ -2527,12 +2558,14 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
else if (sc->driver_info & AUTO_ANNEX_B)
sc->annex = ANNEXB;
else
sc->annex = (le16_to_cpu(sc->usb_dev->descriptor.bcdDevice) & 0x80)?ANNEXB:ANNEXA;
sc->annex = (le16_to_cpu
(sc->usb_dev->descriptor.bcdDevice) & 0x80) ? ANNEXB : ANNEXA;
alt = altsetting[sc->modem_index];
/* ADI930 don't support iso */
if (UEA_CHIP_VERSION(id) != ADI930 && alt > 0) {
if (alt <= 8 && usb_set_interface(usb, UEA_DS_IFACE_NO, alt) == 0) {
if (alt <= 8 &&
usb_set_interface(usb, UEA_DS_IFACE_NO, alt) == 0) {
uea_dbg(usb, "set alternate %u for 2 interface\n", alt);
uea_info(usb, "using iso mode\n");
usbatm->flags |= UDSL_USE_ISOC | UDSL_IGNORE_EILSEQ;
@ -2621,40 +2654,74 @@ static void uea_disconnect(struct usb_interface *intf)
* List of supported VID/PID
*/
static const struct usb_device_id uea_ids[] = {
{USB_DEVICE(ANALOG_VID, ADI930_PID_PREFIRM), .driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ANALOG_VID, ADI930_PID_PSTFIRM), .driver_info = ADI930 | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_I_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_I_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_II_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_II_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IIC_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IIC_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_III_PID_PREFIRM), .driver_info = EAGLE_III | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_III_PID_PSTFIRM), .driver_info = EAGLE_III | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IV_PID_PREFIRM), .driver_info = EAGLE_IV | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IV_PID_PSTFIRM), .driver_info = EAGLE_IV | PSTFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_A_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_A_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_B_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_B_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_A_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_A_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_B_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_B_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(ELSA_VID, ELSA_PID_PREFIRM), .driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_PSTFIRM), .driver_info = ADI930 | PSTFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_A_PREFIRM), .driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_A_PSTFIRM), .driver_info = ADI930 | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(ELSA_VID, ELSA_PID_B_PREFIRM), .driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_B_PSTFIRM), .driver_info = ADI930 | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(USR_VID, MILLER_A_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, MILLER_A_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(USR_VID, MILLER_B_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, MILLER_B_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(USR_VID, HEINEKEN_A_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, HEINEKEN_A_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(USR_VID, HEINEKEN_B_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, HEINEKEN_B_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(ANALOG_VID, ADI930_PID_PREFIRM),
.driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ANALOG_VID, ADI930_PID_PSTFIRM),
.driver_info = ADI930 | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_I_PID_PREFIRM),
.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_I_PID_PSTFIRM),
.driver_info = EAGLE_I | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_II_PID_PREFIRM),
.driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_II_PID_PSTFIRM),
.driver_info = EAGLE_II | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IIC_PID_PREFIRM),
.driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IIC_PID_PSTFIRM),
.driver_info = EAGLE_II | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_III_PID_PREFIRM),
.driver_info = EAGLE_III | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_III_PID_PSTFIRM),
.driver_info = EAGLE_III | PSTFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IV_PID_PREFIRM),
.driver_info = EAGLE_IV | PREFIRM},
{USB_DEVICE(ANALOG_VID, EAGLE_IV_PID_PSTFIRM),
.driver_info = EAGLE_IV | PSTFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_A_PID_PREFIRM),
.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_A_PID_PSTFIRM),
.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_B_PID_PREFIRM),
.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_B_PID_PSTFIRM),
.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_A_PID_PREFIRM),
.driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_A_PID_PSTFIRM),
.driver_info = EAGLE_II | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_B_PID_PREFIRM),
.driver_info = EAGLE_II | PREFIRM},
{USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_B_PID_PSTFIRM),
.driver_info = EAGLE_II | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(ELSA_VID, ELSA_PID_PREFIRM),
.driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_PSTFIRM),
.driver_info = ADI930 | PSTFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_A_PREFIRM),
.driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_A_PSTFIRM),
.driver_info = ADI930 | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(ELSA_VID, ELSA_PID_B_PREFIRM),
.driver_info = ADI930 | PREFIRM},
{USB_DEVICE(ELSA_VID, ELSA_PID_B_PSTFIRM),
.driver_info = ADI930 | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(USR_VID, MILLER_A_PID_PREFIRM),
.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, MILLER_A_PID_PSTFIRM),
.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(USR_VID, MILLER_B_PID_PREFIRM),
.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, MILLER_B_PID_PSTFIRM),
.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
{USB_DEVICE(USR_VID, HEINEKEN_A_PID_PREFIRM),
.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, HEINEKEN_A_PID_PSTFIRM),
.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A},
{USB_DEVICE(USR_VID, HEINEKEN_B_PID_PREFIRM),
.driver_info = EAGLE_I | PREFIRM},
{USB_DEVICE(USR_VID, HEINEKEN_B_PID_PSTFIRM),
.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B},
{}
};

View File

@ -28,7 +28,7 @@
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/usb.h>
#include "../core/hcd.h"
#include <linux/usb/hcd.h>
#include "c67x00.h"
/*

View File

@ -892,7 +892,7 @@ static void acm_write_buffers_free(struct acm *acm)
struct usb_device *usb_dev = interface_to_usbdev(acm->control);
for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++)
usb_buffer_free(usb_dev, acm->writesize, wb->buf, wb->dmah);
usb_free_coherent(usb_dev, acm->writesize, wb->buf, wb->dmah);
}
static void acm_read_buffers_free(struct acm *acm)
@ -901,8 +901,8 @@ static void acm_read_buffers_free(struct acm *acm)
int i, n = acm->rx_buflimit;
for (i = 0; i < n; i++)
usb_buffer_free(usb_dev, acm->readsize,
acm->rb[i].base, acm->rb[i].dma);
usb_free_coherent(usb_dev, acm->readsize,
acm->rb[i].base, acm->rb[i].dma);
}
/* Little helper: write buffers allocate */
@ -912,13 +912,13 @@ static int acm_write_buffers_alloc(struct acm *acm)
struct acm_wb *wb;
for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) {
wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL,
wb->buf = usb_alloc_coherent(acm->dev, acm->writesize, GFP_KERNEL,
&wb->dmah);
if (!wb->buf) {
while (i != 0) {
--i;
--wb;
usb_buffer_free(acm->dev, acm->writesize,
usb_free_coherent(acm->dev, acm->writesize,
wb->buf, wb->dmah);
}
return -ENOMEM;
@ -1177,7 +1177,7 @@ made_compressed_probe:
tty_port_init(&acm->port);
acm->port.ops = &acm_port_ops;
buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
if (!buf) {
dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)\n");
goto alloc_fail2;
@ -1210,11 +1210,11 @@ made_compressed_probe:
for (i = 0; i < num_rx_buf; i++) {
struct acm_rb *rb = &(acm->rb[i]);
rb->base = usb_buffer_alloc(acm->dev, readsize,
rb->base = usb_alloc_coherent(acm->dev, readsize,
GFP_KERNEL, &rb->dma);
if (!rb->base) {
dev_dbg(&intf->dev,
"out of memory (read bufs usb_buffer_alloc)\n");
"out of memory (read bufs usb_alloc_coherent)\n");
goto alloc_fail7;
}
}
@ -1306,7 +1306,7 @@ alloc_fail7:
alloc_fail5:
acm_write_buffers_free(acm);
alloc_fail4:
usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
alloc_fail2:
kfree(acm);
alloc_fail:
@ -1356,8 +1356,8 @@ static void acm_disconnect(struct usb_interface *intf)
stop_data_traffic(acm);
acm_write_buffers_free(acm);
usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer,
acm->ctrl_dma);
usb_free_coherent(usb_dev, acm->ctrlsize, acm->ctrl_buffer,
acm->ctrl_dma);
acm_read_buffers_free(acm);
if (!acm->combined_interfaces)

View File

@ -124,8 +124,8 @@ struct acm {
unsigned char clocal; /* termios CLOCAL */
unsigned int ctrl_caps; /* control capabilities from the class specific header */
unsigned int susp_count; /* number of suspended interfaces */
int combined_interfaces:1; /* control and data collapsed */
int is_int_ep:1; /* interrupt endpoints contrary to spec used */
unsigned int combined_interfaces:1; /* control and data collapsed */
unsigned int is_int_ep:1; /* interrupt endpoints contrary to spec used */
u8 bInterval;
struct acm_wb *delayed_wb; /* write queued for a device about to be woken */
};

View File

@ -276,14 +276,14 @@ static void free_urbs(struct wdm_device *desc)
static void cleanup(struct wdm_device *desc)
{
usb_buffer_free(interface_to_usbdev(desc->intf),
desc->wMaxPacketSize,
desc->sbuf,
desc->validity->transfer_dma);
usb_buffer_free(interface_to_usbdev(desc->intf),
desc->wMaxCommand,
desc->inbuf,
desc->response->transfer_dma);
usb_free_coherent(interface_to_usbdev(desc->intf),
desc->wMaxPacketSize,
desc->sbuf,
desc->validity->transfer_dma);
usb_free_coherent(interface_to_usbdev(desc->intf),
desc->wMaxCommand,
desc->inbuf,
desc->response->transfer_dma);
kfree(desc->orq);
kfree(desc->irq);
kfree(desc->ubuf);
@ -705,17 +705,17 @@ next_desc:
if (!desc->ubuf)
goto err;
desc->sbuf = usb_buffer_alloc(interface_to_usbdev(intf),
desc->sbuf = usb_alloc_coherent(interface_to_usbdev(intf),
desc->wMaxPacketSize,
GFP_KERNEL,
&desc->validity->transfer_dma);
if (!desc->sbuf)
goto err;
desc->inbuf = usb_buffer_alloc(interface_to_usbdev(intf),
desc->bMaxPacketSize0,
GFP_KERNEL,
&desc->response->transfer_dma);
desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf),
desc->bMaxPacketSize0,
GFP_KERNEL,
&desc->response->transfer_dma);
if (!desc->inbuf)
goto err2;
@ -742,15 +742,15 @@ out:
return rv;
err3:
usb_set_intfdata(intf, NULL);
usb_buffer_free(interface_to_usbdev(desc->intf),
desc->bMaxPacketSize0,
usb_free_coherent(interface_to_usbdev(desc->intf),
desc->bMaxPacketSize0,
desc->inbuf,
desc->response->transfer_dma);
err2:
usb_buffer_free(interface_to_usbdev(desc->intf),
desc->wMaxPacketSize,
desc->sbuf,
desc->validity->transfer_dma);
usb_free_coherent(interface_to_usbdev(desc->intf),
desc->wMaxPacketSize,
desc->sbuf,
desc->validity->transfer_dma);
err:
free_urbs(desc);
kfree(desc->ubuf);

View File

@ -27,7 +27,7 @@
* v0.11 - add proto_bias option (Pete Zaitcev)
* v0.12 - add hpoj.sourceforge.net ioctls (David Paschal)
* v0.13 - alloc space for statusbuf (<status> not on stack);
* use usb_buffer_alloc() for read buf & write buf;
* use usb_alloc_coherent() for read buf & write buf;
* none - Maintained in Linux kernel after v0.13
*/

View File

@ -14,7 +14,7 @@
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/usb.h>
#include "hcd.h"
#include <linux/usb/hcd.h>
/*

View File

@ -1,12 +1,14 @@
#include <linux/usb.h>
#include <linux/usb/ch9.h>
#include <linux/usb/hcd.h>
#include <linux/usb/quirks.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <asm/byteorder.h>
#include "usb.h"
#include "hcd.h"
#define USB_MAXALTSETTING 128 /* Hard limit */
#define USB_MAXENDPOINTS 30 /* Hard limit */
@ -19,32 +21,6 @@ static inline const char *plural(int n)
return (n == 1 ? "" : "s");
}
/* FIXME: this is a kludge */
static int find_next_descriptor_more(unsigned char *buffer, int size,
int dt1, int dt2, int dt3, int *num_skipped)
{
struct usb_descriptor_header *h;
int n = 0;
unsigned char *buffer0 = buffer;
/* Find the next descriptor of type dt1 or dt2 or dt3 */
while (size > 0) {
h = (struct usb_descriptor_header *) buffer;
if (h->bDescriptorType == dt1 || h->bDescriptorType == dt2 ||
h->bDescriptorType == dt3)
break;
buffer += h->bLength;
size -= h->bLength;
++n;
}
/* Store the number of descriptors skipped and return the
* number of bytes skipped */
if (num_skipped)
*num_skipped = n;
return buffer - buffer0;
}
static int find_next_descriptor(unsigned char *buffer, int size,
int dt1, int dt2, int *num_skipped)
{
@ -69,47 +45,41 @@ static int find_next_descriptor(unsigned char *buffer, int size,
return buffer - buffer0;
}
static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
int inum, int asnum, struct usb_host_endpoint *ep,
int num_ep, unsigned char *buffer, int size)
unsigned char *buffer, int size)
{
unsigned char *buffer_start = buffer;
struct usb_ss_ep_comp_descriptor *desc;
int retval;
int num_skipped;
struct usb_ss_ep_comp_descriptor *desc;
int max_tx;
int i;
/* The SuperSpeed endpoint companion descriptor is supposed to
* be the first thing immediately following the endpoint descriptor.
*/
desc = (struct usb_ss_ep_comp_descriptor *) buffer;
if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) {
if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP ||
size < USB_DT_SS_EP_COMP_SIZE) {
dev_warn(ddev, "No SuperSpeed endpoint companion for config %d "
" interface %d altsetting %d ep %d: "
"using minimum values\n",
cfgno, inum, asnum, ep->desc.bEndpointAddress);
/*
* The next descriptor is for an Endpoint or Interface,
* no extra descriptors to copy into the companion structure,
* and we didn't eat up any of the buffer.
*/
return 0;
}
memcpy(&ep->ss_ep_comp->desc, desc, USB_DT_SS_EP_COMP_SIZE);
desc = &ep->ss_ep_comp->desc;
buffer += desc->bLength;
size -= desc->bLength;
/* Eat up the other descriptors we don't care about */
ep->ss_ep_comp->extra = buffer;
i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
USB_DT_INTERFACE, &num_skipped);
ep->ss_ep_comp->extralen = i;
buffer += i;
size -= i;
retval = buffer - buffer_start;
if (num_skipped > 0)
dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
num_skipped, plural(num_skipped),
"SuperSpeed endpoint companion");
/* Fill in some default values.
* Leave bmAttributes as zero, which will mean no streams for
* bulk, and isoc won't support multiple bursts of packets.
* With bursts of only one packet, and a Mult of 1, the max
* amount of data moved per endpoint service interval is one
* packet.
*/
ep->ss_ep_comp.bLength = USB_DT_SS_EP_COMP_SIZE;
ep->ss_ep_comp.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
if (usb_endpoint_xfer_isoc(&ep->desc) ||
usb_endpoint_xfer_int(&ep->desc))
ep->ss_ep_comp.wBytesPerInterval =
ep->desc.wMaxPacketSize;
return;
}
memcpy(&ep->ss_ep_comp, desc, USB_DT_SS_EP_COMP_SIZE);
/* Check the various values */
if (usb_endpoint_xfer_control(&ep->desc) && desc->bMaxBurst != 0) {
@ -117,47 +87,48 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
"config %d interface %d altsetting %d ep %d: "
"setting to zero\n", desc->bMaxBurst,
cfgno, inum, asnum, ep->desc.bEndpointAddress);
desc->bMaxBurst = 0;
}
if (desc->bMaxBurst > 15) {
ep->ss_ep_comp.bMaxBurst = 0;
} else if (desc->bMaxBurst > 15) {
dev_warn(ddev, "Endpoint with bMaxBurst = %d in "
"config %d interface %d altsetting %d ep %d: "
"setting to 15\n", desc->bMaxBurst,
cfgno, inum, asnum, ep->desc.bEndpointAddress);
desc->bMaxBurst = 15;
ep->ss_ep_comp.bMaxBurst = 15;
}
if ((usb_endpoint_xfer_control(&ep->desc) || usb_endpoint_xfer_int(&ep->desc))
&& desc->bmAttributes != 0) {
if ((usb_endpoint_xfer_control(&ep->desc) ||
usb_endpoint_xfer_int(&ep->desc)) &&
desc->bmAttributes != 0) {
dev_warn(ddev, "%s endpoint with bmAttributes = %d in "
"config %d interface %d altsetting %d ep %d: "
"setting to zero\n",
usb_endpoint_xfer_control(&ep->desc) ? "Control" : "Bulk",
desc->bmAttributes,
cfgno, inum, asnum, ep->desc.bEndpointAddress);
desc->bmAttributes = 0;
}
if (usb_endpoint_xfer_bulk(&ep->desc) && desc->bmAttributes > 16) {
ep->ss_ep_comp.bmAttributes = 0;
} else if (usb_endpoint_xfer_bulk(&ep->desc) &&
desc->bmAttributes > 16) {
dev_warn(ddev, "Bulk endpoint with more than 65536 streams in "
"config %d interface %d altsetting %d ep %d: "
"setting to max\n",
cfgno, inum, asnum, ep->desc.bEndpointAddress);
desc->bmAttributes = 16;
}
if (usb_endpoint_xfer_isoc(&ep->desc) && desc->bmAttributes > 2) {
ep->ss_ep_comp.bmAttributes = 16;
} else if (usb_endpoint_xfer_isoc(&ep->desc) &&
desc->bmAttributes > 2) {
dev_warn(ddev, "Isoc endpoint has Mult of %d in "
"config %d interface %d altsetting %d ep %d: "
"setting to 3\n", desc->bmAttributes + 1,
cfgno, inum, asnum, ep->desc.bEndpointAddress);
desc->bmAttributes = 2;
ep->ss_ep_comp.bmAttributes = 2;
}
if (usb_endpoint_xfer_isoc(&ep->desc)) {
if (usb_endpoint_xfer_isoc(&ep->desc))
max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1) *
(desc->bmAttributes + 1);
} else if (usb_endpoint_xfer_int(&ep->desc)) {
else if (usb_endpoint_xfer_int(&ep->desc))
max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1);
} else {
goto valid;
}
else
max_tx = 999999;
if (desc->wBytesPerInterval > max_tx) {
dev_warn(ddev, "%s endpoint with wBytesPerInterval of %d in "
"config %d interface %d altsetting %d ep %d: "
@ -166,10 +137,8 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
desc->wBytesPerInterval,
cfgno, inum, asnum, ep->desc.bEndpointAddress,
max_tx);
desc->wBytesPerInterval = max_tx;
ep->ss_ep_comp.wBytesPerInterval = max_tx;
}
valid:
return retval;
}
static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
@ -291,61 +260,19 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
cfgno, inum, asnum, d->bEndpointAddress,
maxp);
}
/* Allocate room for and parse any SS endpoint companion descriptors */
if (to_usb_device(ddev)->speed == USB_SPEED_SUPER) {
endpoint->extra = buffer;
i = find_next_descriptor_more(buffer, size, USB_DT_SS_ENDPOINT_COMP,
USB_DT_ENDPOINT, USB_DT_INTERFACE, &n);
endpoint->extralen = i;
buffer += i;
size -= i;
/* Allocate space for the SS endpoint companion descriptor */
endpoint->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp),
GFP_KERNEL);
if (!endpoint->ss_ep_comp)
return -ENOMEM;
/* Parse a possible SuperSpeed endpoint companion descriptor */
if (to_usb_device(ddev)->speed == USB_SPEED_SUPER)
usb_parse_ss_endpoint_companion(ddev, cfgno,
inum, asnum, endpoint, buffer, size);
/* Fill in some default values (may be overwritten later) */
endpoint->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE;
endpoint->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
endpoint->ss_ep_comp->desc.bMaxBurst = 0;
/*
* Leave bmAttributes as zero, which will mean no streams for
* bulk, and isoc won't support multiple bursts of packets.
* With bursts of only one packet, and a Mult of 1, the max
* amount of data moved per endpoint service interval is one
* packet.
*/
if (usb_endpoint_xfer_isoc(&endpoint->desc) ||
usb_endpoint_xfer_int(&endpoint->desc))
endpoint->ss_ep_comp->desc.wBytesPerInterval =
endpoint->desc.wMaxPacketSize;
if (size > 0) {
retval = usb_parse_ss_endpoint_companion(ddev, cfgno,
inum, asnum, endpoint, num_ep, buffer,
size);
if (retval >= 0) {
buffer += retval;
retval = buffer - buffer0;
}
} else {
dev_warn(ddev, "config %d interface %d altsetting %d "
"endpoint 0x%X has no "
"SuperSpeed companion descriptor\n",
cfgno, inum, asnum, d->bEndpointAddress);
retval = buffer - buffer0;
}
} else {
/* Skip over any Class Specific or Vendor Specific descriptors;
* find the next endpoint or interface descriptor */
endpoint->extra = buffer;
i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
USB_DT_INTERFACE, &n);
endpoint->extralen = i;
retval = buffer - buffer0 + i;
}
/* Skip over any Class Specific or Vendor Specific descriptors;
* find the next endpoint or interface descriptor */
endpoint->extra = buffer;
i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
USB_DT_INTERFACE, &n);
endpoint->extralen = i;
retval = buffer - buffer0 + i;
if (n > 0)
dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
n, plural(n), "endpoint");
@ -478,9 +405,10 @@ skip_to_next_interface_descriptor:
return buffer - buffer0 + i;
}
static int usb_parse_configuration(struct device *ddev, int cfgidx,
static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
struct usb_host_config *config, unsigned char *buffer, int size)
{
struct device *ddev = &dev->dev;
unsigned char *buffer0 = buffer;
int cfgno;
int nintf, nintf_orig;
@ -549,6 +477,16 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
}
inum = d->bInterfaceNumber;
if ((dev->quirks & USB_QUIRK_HONOR_BNUMINTERFACES) &&
n >= nintf_orig) {
dev_warn(ddev, "config %d has more interface "
"descriptors, than it declares in "
"bNumInterfaces, ignoring interface "
"number: %d\n", cfgno, inum);
continue;
}
if (inum >= nintf_orig)
dev_warn(ddev, "config %d has an invalid "
"interface number: %d but max is %d\n",
@ -722,7 +660,6 @@ int usb_get_configuration(struct usb_device *dev)
int ncfg = dev->descriptor.bNumConfigurations;
int result = 0;
unsigned int cfgno, length;
unsigned char *buffer;
unsigned char *bigbuffer;
struct usb_config_descriptor *desc;
@ -751,17 +688,16 @@ int usb_get_configuration(struct usb_device *dev)
if (!dev->rawdescriptors)
goto err2;
buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
if (!buffer)
desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
if (!desc)
goto err2;
desc = (struct usb_config_descriptor *)buffer;
result = 0;
for (; cfgno < ncfg; cfgno++) {
/* We grab just the first descriptor so we know how long
* the whole configuration is */
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
buffer, USB_DT_CONFIG_SIZE);
desc, USB_DT_CONFIG_SIZE);
if (result < 0) {
dev_err(ddev, "unable to read config index %d "
"descriptor/%s: %d\n", cfgno, "start", result);
@ -800,7 +736,7 @@ int usb_get_configuration(struct usb_device *dev)
dev->rawdescriptors[cfgno] = bigbuffer;
result = usb_parse_configuration(&dev->dev, cfgno,
result = usb_parse_configuration(dev, cfgno,
&dev->config[cfgno], bigbuffer, length);
if (result < 0) {
++cfgno;
@ -810,7 +746,7 @@ int usb_get_configuration(struct usb_device *dev)
result = 0;
err:
kfree(buffer);
kfree(desc);
out_not_authorized:
dev->descriptor.bNumConfigurations = cfgno;
err2:

View File

@ -1,7 +1,8 @@
/*
* devices.c
* (C) Copyright 1999 Randy Dunlap.
* (C) Copyright 1999,2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
* (C) Copyright 1999,2000 Thomas Sailer <sailer@ife.ee.ethz.ch>.
* (proc file per device)
* (C) Copyright 1999 Deti Fliegl (new USB architecture)
*
* This program is free software; you can redistribute it and/or modify
@ -55,11 +56,11 @@
#include <linux/usb.h>
#include <linux/smp_lock.h>
#include <linux/usbdevice_fs.h>
#include <linux/usb/hcd.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <linux/uaccess.h>
#include "usb.h"
#include "hcd.h"
/* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
#define ALLOW_SERIAL_NUMBER
@ -138,8 +139,8 @@ struct class_info {
char *class_name;
};
static const struct class_info clas_info[] =
{ /* max. 5 chars. per name string */
static const struct class_info clas_info[] = {
/* max. 5 chars. per name string */
{USB_CLASS_PER_INTERFACE, ">ifc"},
{USB_CLASS_AUDIO, "audio"},
{USB_CLASS_COMM, "comm."},
@ -191,8 +192,10 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
if (speed == USB_SPEED_HIGH) {
switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) {
case 1 << 11: bandwidth = 2; break;
case 2 << 11: bandwidth = 3; break;
case 1 << 11:
bandwidth = 2; break;
case 2 << 11:
bandwidth = 3; break;
}
}
@ -200,7 +203,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_CONTROL:
type = "Ctrl";
if (speed == USB_SPEED_HIGH) /* uframes per NAK */
if (speed == USB_SPEED_HIGH) /* uframes per NAK */
interval = desc->bInterval;
else
interval = 0;

View File

@ -43,6 +43,7 @@
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
#include <linux/usb/hcd.h> /* for usbcore internals */
#include <linux/cdev.h>
#include <linux/notifier.h>
#include <linux/security.h>
@ -50,9 +51,7 @@
#include <asm/byteorder.h>
#include <linux/moduleparam.h>
#include "hcd.h" /* for usbcore internals */
#include "usb.h"
#include "hub.h"
#define USB_MAXBUS 64
#define USB_DEVICE_MAX USB_MAXBUS * 128

View File

@ -26,8 +26,9 @@
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/usb/quirks.h>
#include <linux/usb/hcd.h>
#include <linux/pm_runtime.h>
#include "hcd.h"
#include "usb.h"
@ -333,7 +334,8 @@ static int usb_probe_interface(struct device *dev)
usb_cancel_queued_reset(intf);
/* Unbound interfaces are always runtime-PM-disabled and -suspended */
pm_runtime_disable(dev);
if (driver->supports_autosuspend)
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
usb_autosuspend_device(udev);
@ -388,7 +390,8 @@ static int usb_unbind_interface(struct device *dev)
intf->needs_remote_wakeup = 0;
/* Unbound interfaces are always runtime-PM-disabled and -suspended */
pm_runtime_disable(dev);
if (driver->supports_autosuspend)
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
/* Undo any residual pm_autopm_get_interface_* calls */
@ -437,14 +440,17 @@ int usb_driver_claim_interface(struct usb_driver *driver,
iface->condition = USB_INTERFACE_BOUND;
/* Claimed interfaces are initially inactive (suspended). They are
* runtime-PM-enabled only if the driver has autosuspend support.
* They are sensitive to their children's power states.
/* Claimed interfaces are initially inactive (suspended) and
* runtime-PM-enabled, but only if the driver has autosuspend
* support. Otherwise they are marked active, to prevent the
* device from being autosuspended, but left disabled. In either
* case they are sensitive to their children's power states.
*/
pm_runtime_set_suspended(dev);
pm_suspend_ignore_children(dev, false);
if (driver->supports_autosuspend)
pm_runtime_enable(dev);
else
pm_runtime_set_active(dev);
/* if interface was already added, bind now; else let
* the future device_add() bind it, bypassing probe()
@ -1355,13 +1361,9 @@ int usb_resume(struct device *dev, pm_message_t msg)
*
* The caller must hold @udev's device lock.
*/
int usb_enable_autosuspend(struct usb_device *udev)
void usb_enable_autosuspend(struct usb_device *udev)
{
if (udev->autosuspend_disabled) {
udev->autosuspend_disabled = 0;
usb_autosuspend_device(udev);
}
return 0;
pm_runtime_allow(&udev->dev);
}
EXPORT_SYMBOL_GPL(usb_enable_autosuspend);
@ -1374,16 +1376,9 @@ EXPORT_SYMBOL_GPL(usb_enable_autosuspend);
*
* The caller must hold @udev's device lock.
*/
int usb_disable_autosuspend(struct usb_device *udev)
void usb_disable_autosuspend(struct usb_device *udev)
{
int rc = 0;
if (!udev->autosuspend_disabled) {
rc = usb_autoresume_device(udev);
if (rc == 0)
udev->autosuspend_disabled = 1;
}
return rc;
pm_runtime_forbid(&udev->dev);
}
EXPORT_SYMBOL_GPL(usb_disable_autosuspend);
@ -1485,9 +1480,6 @@ int usb_autoresume_device(struct usb_device *udev)
* 0, a delayed autosuspend request for @intf's device is attempted. The
* attempt may fail (see autosuspend_check()).
*
* If the driver has set @intf->needs_remote_wakeup then autosuspend will
* take place only if the device's remote-wakeup facility is enabled.
*
* This routine can run only in process context.
*/
void usb_autopm_put_interface(struct usb_interface *intf)
@ -1530,7 +1522,7 @@ void usb_autopm_put_interface_async(struct usb_interface *intf)
atomic_dec(&intf->pm_usage_cnt);
pm_runtime_put_noidle(&intf->dev);
if (!udev->autosuspend_disabled) {
if (udev->dev.power.runtime_auto) {
/* Optimization: Don't schedule a delayed autosuspend if
* the timer is already running and the expiration time
* wouldn't change.
@ -1672,14 +1664,14 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume);
/* Internal routine to check whether we may autosuspend a device. */
static int autosuspend_check(struct usb_device *udev)
{
int i;
int w, i;
struct usb_interface *intf;
unsigned long suspend_time, j;
/* Fail if autosuspend is disabled, or any interfaces are in use, or
* any interface drivers require remote wakeup but it isn't available.
*/
udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
w = 0;
if (udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i];
@ -1693,12 +1685,7 @@ static int autosuspend_check(struct usb_device *udev)
continue;
if (atomic_read(&intf->dev.power.usage_count) > 0)
return -EBUSY;
if (intf->needs_remote_wakeup &&
!udev->do_remote_wakeup) {
dev_dbg(&udev->dev, "remote wakeup needed "
"for autosuspend\n");
return -EOPNOTSUPP;
}
w |= intf->needs_remote_wakeup;
/* Don't allow autosuspend if the device will need
* a reset-resume and any of its interface drivers
@ -1714,6 +1701,11 @@ static int autosuspend_check(struct usb_device *udev)
}
}
}
if (w && !device_can_wakeup(&udev->dev)) {
dev_dbg(&udev->dev, "remote wakeup needed for autosuspend\n");
return -EOPNOTSUPP;
}
udev->do_remote_wakeup = w;
/* If everything is okay but the device hasn't been idle for long
* enough, queue a delayed autosuspend request.

View File

@ -18,8 +18,8 @@
*/
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include "usb.h"
#include "hcd.h"
static inline const char *plural(int n)
{

View File

@ -21,6 +21,7 @@
#include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <asm/io.h>
#include <asm/irq.h>
@ -33,7 +34,6 @@
#endif
#include "usb.h"
#include "hcd.h"
/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */

View File

@ -38,14 +38,12 @@
#include <asm/unaligned.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/pm_runtime.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include "usb.h"
#include "hcd.h"
#include "hub.h"
/*-------------------------------------------------------------------------*/
@ -1261,6 +1259,51 @@ static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle,
*dma_handle = 0;
}
static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
{
enum dma_data_direction dir;
if (urb->transfer_flags & URB_SETUP_MAP_SINGLE)
dma_unmap_single(hcd->self.controller,
urb->setup_dma,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
else if (urb->transfer_flags & URB_SETUP_MAP_LOCAL)
hcd_free_coherent(urb->dev->bus,
&urb->setup_dma,
(void **) &urb->setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
if (urb->transfer_flags & URB_DMA_MAP_SG)
dma_unmap_sg(hcd->self.controller,
urb->sg,
urb->num_sgs,
dir);
else if (urb->transfer_flags & URB_DMA_MAP_PAGE)
dma_unmap_page(hcd->self.controller,
urb->transfer_dma,
urb->transfer_buffer_length,
dir);
else if (urb->transfer_flags & URB_DMA_MAP_SINGLE)
dma_unmap_single(hcd->self.controller,
urb->transfer_dma,
urb->transfer_buffer_length,
dir);
else if (urb->transfer_flags & URB_MAP_LOCAL)
hcd_free_coherent(urb->dev->bus,
&urb->transfer_dma,
&urb->transfer_buffer,
urb->transfer_buffer_length,
dir);
/* Make it safe to call this routine more than once */
urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
URB_DMA_MAP_SG | URB_DMA_MAP_PAGE |
URB_DMA_MAP_SINGLE | URB_MAP_LOCAL);
}
static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
gfp_t mem_flags)
{
@ -1272,11 +1315,8 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
* unless it uses pio or talks to another transport,
* or uses the provided scatter gather list for bulk.
*/
if (is_root_hub(urb->dev))
return 0;
if (usb_endpoint_xfer_control(&urb->ep->desc)
&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
if (usb_endpoint_xfer_control(&urb->ep->desc)) {
if (hcd->self.uses_dma) {
urb->setup_dma = dma_map_single(
hcd->self.controller,
@ -1286,27 +1326,64 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
if (dma_mapping_error(hcd->self.controller,
urb->setup_dma))
return -EAGAIN;
} else if (hcd->driver->flags & HCD_LOCAL_MEM)
urb->transfer_flags |= URB_SETUP_MAP_SINGLE;
} else if (hcd->driver->flags & HCD_LOCAL_MEM) {
ret = hcd_alloc_coherent(
urb->dev->bus, mem_flags,
&urb->setup_dma,
(void **)&urb->setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
if (ret)
return ret;
urb->transfer_flags |= URB_SETUP_MAP_LOCAL;
}
}
dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
if (ret == 0 && urb->transfer_buffer_length != 0
if (urb->transfer_buffer_length != 0
&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
if (hcd->self.uses_dma) {
urb->transfer_dma = dma_map_single (
hcd->self.controller,
urb->transfer_buffer,
urb->transfer_buffer_length,
dir);
if (dma_mapping_error(hcd->self.controller,
if (urb->num_sgs) {
int n = dma_map_sg(
hcd->self.controller,
urb->sg,
urb->num_sgs,
dir);
if (n <= 0)
ret = -EAGAIN;
else
urb->transfer_flags |= URB_DMA_MAP_SG;
if (n != urb->num_sgs) {
urb->num_sgs = n;
urb->transfer_flags |=
URB_DMA_SG_COMBINED;
}
} else if (urb->sg) {
struct scatterlist *sg = urb->sg;
urb->transfer_dma = dma_map_page(
hcd->self.controller,
sg_page(sg),
sg->offset,
urb->transfer_buffer_length,
dir);
if (dma_mapping_error(hcd->self.controller,
urb->transfer_dma))
return -EAGAIN;
ret = -EAGAIN;
else
urb->transfer_flags |= URB_DMA_MAP_PAGE;
} else {
urb->transfer_dma = dma_map_single(
hcd->self.controller,
urb->transfer_buffer,
urb->transfer_buffer_length,
dir);
if (dma_mapping_error(hcd->self.controller,
urb->transfer_dma))
ret = -EAGAIN;
else
urb->transfer_flags |= URB_DMA_MAP_SINGLE;
}
} else if (hcd->driver->flags & HCD_LOCAL_MEM) {
ret = hcd_alloc_coherent(
urb->dev->bus, mem_flags,
@ -1314,55 +1391,16 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
&urb->transfer_buffer,
urb->transfer_buffer_length,
dir);
if (ret && usb_endpoint_xfer_control(&urb->ep->desc)
&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
hcd_free_coherent(urb->dev->bus,
&urb->setup_dma,
(void **)&urb->setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
if (ret == 0)
urb->transfer_flags |= URB_MAP_LOCAL;
}
if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE |
URB_SETUP_MAP_LOCAL)))
unmap_urb_for_dma(hcd, urb);
}
return ret;
}
static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
{
enum dma_data_direction dir;
if (is_root_hub(urb->dev))
return;
if (usb_endpoint_xfer_control(&urb->ep->desc)
&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
if (hcd->self.uses_dma)
dma_unmap_single(hcd->self.controller, urb->setup_dma,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
else if (hcd->driver->flags & HCD_LOCAL_MEM)
hcd_free_coherent(urb->dev->bus, &urb->setup_dma,
(void **)&urb->setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
}
dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
if (urb->transfer_buffer_length != 0
&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
if (hcd->self.uses_dma)
dma_unmap_single(hcd->self.controller,
urb->transfer_dma,
urb->transfer_buffer_length,
dir);
else if (hcd->driver->flags & HCD_LOCAL_MEM)
hcd_free_coherent(urb->dev->bus, &urb->transfer_dma,
&urb->transfer_buffer,
urb->transfer_buffer_length,
dir);
}
}
/*-------------------------------------------------------------------------*/
/* may be called in any context with a valid urb->dev usecount
@ -1391,21 +1429,20 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
* URBs must be submitted in process context with interrupts
* enabled.
*/
status = map_urb_for_dma(hcd, urb, mem_flags);
if (unlikely(status)) {
usbmon_urb_submit_error(&hcd->self, urb, status);
goto error;
if (is_root_hub(urb->dev)) {
status = rh_urb_enqueue(hcd, urb);
} else {
status = map_urb_for_dma(hcd, urb, mem_flags);
if (likely(status == 0)) {
status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
if (unlikely(status))
unmap_urb_for_dma(hcd, urb);
}
}
if (is_root_hub(urb->dev))
status = rh_urb_enqueue(hcd, urb);
else
status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
if (unlikely(status)) {
usbmon_urb_submit_error(&hcd->self, urb, status);
unmap_urb_for_dma(hcd, urb);
error:
urb->hcpriv = NULL;
INIT_LIST_HEAD(&urb->urb_list);
atomic_dec(&urb->use_count);
@ -1775,6 +1812,75 @@ void usb_hcd_reset_endpoint(struct usb_device *udev,
}
}
/**
* usb_alloc_streams - allocate bulk endpoint stream IDs.
* @interface: alternate setting that includes all endpoints.
* @eps: array of endpoints that need streams.
* @num_eps: number of endpoints in the array.
* @num_streams: number of streams to allocate.
* @mem_flags: flags hcd should use to allocate memory.
*
* Sets up a group of bulk endpoints to have num_streams stream IDs available.
* Drivers may queue multiple transfers to different stream IDs, which may
* complete in a different order than they were queued.
*/
int usb_alloc_streams(struct usb_interface *interface,
struct usb_host_endpoint **eps, unsigned int num_eps,
unsigned int num_streams, gfp_t mem_flags)
{
struct usb_hcd *hcd;
struct usb_device *dev;
int i;
dev = interface_to_usbdev(interface);
hcd = bus_to_hcd(dev->bus);
if (!hcd->driver->alloc_streams || !hcd->driver->free_streams)
return -EINVAL;
if (dev->speed != USB_SPEED_SUPER)
return -EINVAL;
/* Streams only apply to bulk endpoints. */
for (i = 0; i < num_eps; i++)
if (!usb_endpoint_xfer_bulk(&eps[i]->desc))
return -EINVAL;
return hcd->driver->alloc_streams(hcd, dev, eps, num_eps,
num_streams, mem_flags);
}
EXPORT_SYMBOL_GPL(usb_alloc_streams);
/**
* usb_free_streams - free bulk endpoint stream IDs.
* @interface: alternate setting that includes all endpoints.
* @eps: array of endpoints to remove streams from.
* @num_eps: number of endpoints in the array.
* @mem_flags: flags hcd should use to allocate memory.
*
* Reverts a group of bulk endpoints back to not using stream IDs.
* Can fail if we are given bad arguments, or HCD is broken.
*/
void usb_free_streams(struct usb_interface *interface,
struct usb_host_endpoint **eps, unsigned int num_eps,
gfp_t mem_flags)
{
struct usb_hcd *hcd;
struct usb_device *dev;
int i;
dev = interface_to_usbdev(interface);
hcd = bus_to_hcd(dev->bus);
if (dev->speed != USB_SPEED_SUPER)
return;
/* Streams only apply to bulk endpoints. */
for (i = 0; i < num_eps; i++)
if (!usb_endpoint_xfer_bulk(&eps[i]->desc))
return;
hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);
}
EXPORT_SYMBOL_GPL(usb_free_streams);
/* Protect against drivers that try to unlink URBs after the device
* is gone, by waiting until all unlinks for @udev are finished.
* Since we don't currently track URBs by device, simply wait until

View File

@ -19,6 +19,7 @@
#include <linux/ioctl.h>
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
#include <linux/usb/hcd.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
#include <linux/freezer.h>
@ -28,8 +29,6 @@
#include <asm/byteorder.h>
#include "usb.h"
#include "hcd.h"
#include "hub.h"
/* if we are in debug mode, always announce new devices */
#ifdef DEBUG
@ -154,11 +153,11 @@ static int usb_reset_and_verify_device(struct usb_device *udev);
static inline char *portspeed(int portstatus)
{
if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED))
if (portstatus & USB_PORT_STAT_HIGH_SPEED)
return "480 Mb/s";
else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED))
else if (portstatus & USB_PORT_STAT_LOW_SPEED)
return "1.5 Mb/s";
else if (portstatus & (1 << USB_PORT_FEAT_SUPERSPEED))
else if (portstatus & USB_PORT_STAT_SUPER_SPEED)
return "5.0 Gb/s";
else
return "12 Mb/s";
@ -745,8 +744,20 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
!(portstatus & USB_PORT_STAT_CONNECTION) ||
!udev ||
udev->state == USB_STATE_NOTATTACHED)) {
clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
portstatus &= ~USB_PORT_STAT_ENABLE;
/*
* USB3 protocol ports will automatically transition
* to Enabled state when detect an USB3.0 device attach.
* Do not disable USB3 protocol ports.
* FIXME: USB3 root hub and external hubs are treated
* differently here.
*/
if (hdev->descriptor.bDeviceProtocol != 3 ||
(!hdev->parent &&
!(portstatus & USB_PORT_STAT_SUPER_SPEED))) {
clear_port_feature(hdev, port1,
USB_PORT_FEAT_ENABLE);
portstatus &= ~USB_PORT_STAT_ENABLE;
}
}
/* Clear status-change flags; we'll debounce later */
@ -1784,7 +1795,6 @@ int usb_new_device(struct usb_device *udev)
* sysfs power/wakeup controls wakeup enabled/disabled
*/
device_init_wakeup(&udev->dev, 0);
device_set_wakeup_enable(&udev->dev, 1);
}
/* Tell the runtime-PM framework the device is active */
@ -3038,7 +3048,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
/* maybe switch power back on (e.g. root hub was reset) */
if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
&& !(portstatus & (1 << USB_PORT_FEAT_POWER)))
&& !(portstatus & USB_PORT_STAT_POWER))
set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
if (portstatus & USB_PORT_STAT_ENABLE)
@ -3076,7 +3086,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if (!(hcd->driver->flags & HCD_USB3))
udev->speed = USB_SPEED_UNKNOWN;
else if ((hdev->parent == NULL) &&
(portstatus & (1 << USB_PORT_FEAT_SUPERSPEED)))
(portstatus & USB_PORT_STAT_SUPER_SPEED))
udev->speed = USB_SPEED_SUPER;
else
udev->speed = USB_SPEED_UNKNOWN;

View File

@ -40,9 +40,9 @@
#include <linux/notifier.h>
#include <linux/seq_file.h>
#include <linux/smp_lock.h>
#include <linux/usb/hcd.h>
#include <asm/byteorder.h>
#include "usb.h"
#include "hcd.h"
#define USBFS_DEFAULT_DEVMODE (S_IWUSR | S_IRUGO)
#define USBFS_DEFAULT_BUSMODE (S_IXUGO | S_IRUGO)

View File

@ -14,9 +14,9 @@
#include <linux/device.h>
#include <linux/scatterlist.h>
#include <linux/usb/quirks.h>
#include <linux/usb/hcd.h> /* for usbcore internals */
#include <asm/byteorder.h>
#include "hcd.h" /* for usbcore internals */
#include "usb.h"
static void cancel_async_set_config(struct usb_device *udev);
@ -226,8 +226,7 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
struct urb *urb;
struct usb_host_endpoint *ep;
ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out)
[usb_pipeendpoint(pipe)];
ep = usb_pipe_endpoint(usb_dev, pipe);
if (!ep || len < 0)
return -EINVAL;
@ -259,9 +258,6 @@ static void sg_clean(struct usb_sg_request *io)
kfree(io->urbs);
io->urbs = NULL;
}
if (io->dev->dev.dma_mask != NULL)
usb_buffer_unmap_sg(io->dev, usb_pipein(io->pipe),
io->sg, io->nents);
io->dev = NULL;
}
@ -364,7 +360,6 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
{
int i;
int urb_flags;
int dma;
int use_sg;
if (!io || !dev || !sg
@ -376,114 +371,76 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
spin_lock_init(&io->lock);
io->dev = dev;
io->pipe = pipe;
io->sg = sg;
io->nents = nents;
/* not all host controllers use DMA (like the mainstream pci ones);
* they can use PIO (sl811) or be software over another transport.
*/
dma = (dev->dev.dma_mask != NULL);
if (dma)
io->entries = usb_buffer_map_sg(dev, usb_pipein(pipe),
sg, nents);
else
io->entries = nents;
/* initialize all the urbs we'll use */
if (io->entries <= 0)
return io->entries;
if (dev->bus->sg_tablesize > 0) {
io->urbs = kmalloc(sizeof *io->urbs, mem_flags);
use_sg = true;
io->entries = 1;
} else {
io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags);
use_sg = false;
io->entries = nents;
}
/* initialize all the urbs we'll use */
io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags);
if (!io->urbs)
goto nomem;
urb_flags = 0;
if (dma)
urb_flags |= URB_NO_TRANSFER_DMA_MAP;
urb_flags = URB_NO_INTERRUPT;
if (usb_pipein(pipe))
urb_flags |= URB_SHORT_NOT_OK;
if (use_sg) {
io->urbs[0] = usb_alloc_urb(0, mem_flags);
if (!io->urbs[0]) {
io->entries = 0;
for_each_sg(sg, sg, io->entries, i) {
struct urb *urb;
unsigned len;
urb = usb_alloc_urb(0, mem_flags);
if (!urb) {
io->entries = i;
goto nomem;
}
io->urbs[i] = urb;
io->urbs[0]->dev = NULL;
io->urbs[0]->pipe = pipe;
io->urbs[0]->interval = period;
io->urbs[0]->transfer_flags = urb_flags;
urb->dev = NULL;
urb->pipe = pipe;
urb->interval = period;
urb->transfer_flags = urb_flags;
urb->complete = sg_complete;
urb->context = io;
urb->sg = sg;
io->urbs[0]->complete = sg_complete;
io->urbs[0]->context = io;
/* A length of zero means transfer the whole sg list */
io->urbs[0]->transfer_buffer_length = length;
if (length == 0) {
for_each_sg(sg, sg, io->entries, i) {
io->urbs[0]->transfer_buffer_length +=
sg_dma_len(sg);
if (use_sg) {
/* There is no single transfer buffer */
urb->transfer_buffer = NULL;
urb->num_sgs = nents;
/* A length of zero means transfer the whole sg list */
len = length;
if (len == 0) {
for_each_sg(sg, sg, nents, i)
len += sg->length;
}
}
io->urbs[0]->sg = io;
io->urbs[0]->num_sgs = io->entries;
io->entries = 1;
} else {
urb_flags |= URB_NO_INTERRUPT;
for_each_sg(sg, sg, io->entries, i) {
unsigned len;
io->urbs[i] = usb_alloc_urb(0, mem_flags);
if (!io->urbs[i]) {
io->entries = i;
goto nomem;
}
io->urbs[i]->dev = NULL;
io->urbs[i]->pipe = pipe;
io->urbs[i]->interval = period;
io->urbs[i]->transfer_flags = urb_flags;
io->urbs[i]->complete = sg_complete;
io->urbs[i]->context = io;
} else {
/*
* Some systems need to revert to PIO when DMA is temporarily
* unavailable. For their sakes, both transfer_buffer and
* transfer_dma are set when possible.
*
* Note that if IOMMU coalescing occurred, we cannot
* trust sg_page anymore, so check if S/G list shrunk.
* Some systems can't use DMA; they use PIO instead.
* For their sakes, transfer_buffer is set whenever
* possible.
*/
if (io->nents == io->entries && !PageHighMem(sg_page(sg)))
io->urbs[i]->transfer_buffer = sg_virt(sg);
if (!PageHighMem(sg_page(sg)))
urb->transfer_buffer = sg_virt(sg);
else
io->urbs[i]->transfer_buffer = NULL;
if (dma) {
io->urbs[i]->transfer_dma = sg_dma_address(sg);
len = sg_dma_len(sg);
} else {
/* hc may use _only_ transfer_buffer */
len = sg->length;
}
urb->transfer_buffer = NULL;
len = sg->length;
if (length) {
len = min_t(unsigned, len, length);
length -= len;
if (length == 0)
io->entries = i + 1;
}
io->urbs[i]->transfer_buffer_length = len;
}
io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT;
urb->transfer_buffer_length = len;
}
io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT;
/* transaction state */
io->count = io->entries;

View File

@ -71,6 +71,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* SKYMEDI USB_DRIVE */
{ USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME },
/* BUILDWIN Photo Frame */
{ USB_DEVICE(0x1908, 0x1315), .driver_info =
USB_QUIRK_HONOR_BNUMINTERFACES },
/* INTEL VALUE SSD */
{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },

View File

@ -383,13 +383,24 @@ static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR,
static const char on_string[] = "on";
static const char auto_string[] = "auto";
static void warn_level(void) {
static int level_warned;
if (!level_warned) {
level_warned = 1;
printk(KERN_WARNING "WARNING! power/level is deprecated; "
"use power/control instead\n");
}
}
static ssize_t
show_level(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_device *udev = to_usb_device(dev);
const char *p = auto_string;
if (udev->state != USB_STATE_SUSPENDED && udev->autosuspend_disabled)
warn_level();
if (udev->state != USB_STATE_SUSPENDED && !udev->dev.power.runtime_auto)
p = on_string;
return sprintf(buf, "%s\n", p);
}
@ -401,8 +412,9 @@ set_level(struct device *dev, struct device_attribute *attr,
struct usb_device *udev = to_usb_device(dev);
int len = count;
char *cp;
int rc;
int rc = count;
warn_level();
cp = memchr(buf, '\n', count);
if (cp)
len = cp - buf;
@ -411,17 +423,17 @@ set_level(struct device *dev, struct device_attribute *attr,
if (len == sizeof on_string - 1 &&
strncmp(buf, on_string, len) == 0)
rc = usb_disable_autosuspend(udev);
usb_disable_autosuspend(udev);
else if (len == sizeof auto_string - 1 &&
strncmp(buf, auto_string, len) == 0)
rc = usb_enable_autosuspend(udev);
usb_enable_autosuspend(udev);
else
rc = -EINVAL;
usb_unlock_device(udev);
return (rc < 0 ? rc : count);
return rc;
}
static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);

View File

@ -6,7 +6,7 @@
#include <linux/log2.h>
#include <linux/usb.h>
#include <linux/wait.h>
#include "hcd.h"
#include <linux/usb/hcd.h>
#define to_urb(d) container_of(d, struct urb, kref)
@ -308,8 +308,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
* will be required to set urb->ep directly and we will eliminate
* urb->pipe.
*/
ep = (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out)
[usb_pipeendpoint(urb->pipe)];
ep = usb_pipe_endpoint(dev, urb->pipe);
if (!ep)
return -ENOENT;
@ -333,9 +332,12 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
is_out = usb_endpoint_dir_out(&ep->desc);
}
/* Cache the direction for later use */
urb->transfer_flags = (urb->transfer_flags & ~URB_DIR_MASK) |
(is_out ? URB_DIR_OUT : URB_DIR_IN);
/* Clear the internal flags and cache the direction for later use */
urb->transfer_flags &= ~(URB_DIR_MASK | URB_DMA_MAP_SINGLE |
URB_DMA_MAP_PAGE | URB_DMA_MAP_SG | URB_MAP_LOCAL |
URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
URB_DMA_SG_COMBINED);
urb->transfer_flags |= (is_out ? URB_DIR_OUT : URB_DIR_IN);
if (xfertype != USB_ENDPOINT_XFER_CONTROL &&
dev->state < USB_STATE_CONFIGURED)
@ -396,8 +398,8 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
return -EPIPE; /* The most suitable error code :-) */
/* enforce simple/standard policy */
allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
URB_NO_INTERRUPT | URB_DIR_MASK | URB_FREE_BUFFER);
allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK |
URB_FREE_BUFFER);
switch (xfertype) {
case USB_ENDPOINT_XFER_BULK:
if (is_out)

View File

@ -32,6 +32,7 @@
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include <linux/debugfs.h>
@ -41,7 +42,6 @@
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include "hcd.h"
#include "usb.h"
@ -593,76 +593,6 @@ int usb_lock_device_for_reset(struct usb_device *udev,
}
EXPORT_SYMBOL_GPL(usb_lock_device_for_reset);
static struct usb_device *match_device(struct usb_device *dev,
u16 vendor_id, u16 product_id)
{
struct usb_device *ret_dev = NULL;
int child;
dev_dbg(&dev->dev, "check for vendor %04x, product %04x ...\n",
le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));
/* see if this device matches */
if ((vendor_id == le16_to_cpu(dev->descriptor.idVendor)) &&
(product_id == le16_to_cpu(dev->descriptor.idProduct))) {
dev_dbg(&dev->dev, "matched this device!\n");
ret_dev = usb_get_dev(dev);
goto exit;
}
/* look through all of the children of this device */
for (child = 0; child < dev->maxchild; ++child) {
if (dev->children[child]) {
usb_lock_device(dev->children[child]);
ret_dev = match_device(dev->children[child],
vendor_id, product_id);
usb_unlock_device(dev->children[child]);
if (ret_dev)
goto exit;
}
}
exit:
return ret_dev;
}
/**
* usb_find_device - find a specific usb device in the system
* @vendor_id: the vendor id of the device to find
* @product_id: the product id of the device to find
*
* Returns a pointer to a struct usb_device if such a specified usb
* device is present in the system currently. The usage count of the
* device will be incremented if a device is found. Make sure to call
* usb_put_dev() when the caller is finished with the device.
*
* If a device with the specified vendor and product id is not found,
* NULL is returned.
*/
struct usb_device *usb_find_device(u16 vendor_id, u16 product_id)
{
struct list_head *buslist;
struct usb_bus *bus;
struct usb_device *dev = NULL;
mutex_lock(&usb_bus_list_lock);
for (buslist = usb_bus_list.next;
buslist != &usb_bus_list;
buslist = buslist->next) {
bus = container_of(buslist, struct usb_bus, bus_list);
if (!bus->root_hub)
continue;
usb_lock_device(bus->root_hub);
dev = match_device(bus->root_hub, vendor_id, product_id);
usb_unlock_device(bus->root_hub);
if (dev)
goto exit;
}
exit:
mutex_unlock(&usb_bus_list_lock);
return dev;
}
/**
* usb_get_current_frame_number - return current bus frame number
* @dev: the device whose bus is being queried
@ -775,7 +705,7 @@ EXPORT_SYMBOL_GPL(usb_free_coherent);
* @urb: urb whose transfer_buffer/setup_packet will be mapped
*
* Return value is either null (indicating no buffer could be mapped), or
* the parameter. URB_NO_TRANSFER_DMA_MAP and URB_NO_SETUP_DMA_MAP are
* the parameter. URB_NO_TRANSFER_DMA_MAP is
* added to urb->transfer_flags if the operation succeeds. If the device
* is connected to this system through a non-DMA controller, this operation
* always succeeds.
@ -803,17 +733,11 @@ struct urb *usb_buffer_map(struct urb *urb)
urb->transfer_buffer, urb->transfer_buffer_length,
usb_pipein(urb->pipe)
? DMA_FROM_DEVICE : DMA_TO_DEVICE);
if (usb_pipecontrol(urb->pipe))
urb->setup_dma = dma_map_single(controller,
urb->setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
/* FIXME generic api broken like pci, can't report errors */
/* if (urb->transfer_dma == DMA_ADDR_INVALID) return 0; */
} else
urb->transfer_dma = ~0;
urb->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP
| URB_NO_SETUP_DMA_MAP);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
return urb;
}
EXPORT_SYMBOL_GPL(usb_buffer_map);
@ -881,18 +805,13 @@ void usb_buffer_unmap(struct urb *urb)
urb->transfer_dma, urb->transfer_buffer_length,
usb_pipein(urb->pipe)
? DMA_FROM_DEVICE : DMA_TO_DEVICE);
if (usb_pipecontrol(urb->pipe))
dma_unmap_single(controller,
urb->setup_dma,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
}
urb->transfer_flags &= ~(URB_NO_TRANSFER_DMA_MAP
| URB_NO_SETUP_DMA_MAP);
urb->transfer_flags &= ~URB_NO_TRANSFER_DMA_MAP;
}
EXPORT_SYMBOL_GPL(usb_buffer_unmap);
#endif /* 0 */
#if 0
/**
* usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint
* @dev: device to which the scatterlist will be mapped
@ -936,6 +855,7 @@ int usb_buffer_map_sg(const struct usb_device *dev, int is_in,
is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE) ? : -ENOMEM;
}
EXPORT_SYMBOL_GPL(usb_buffer_map_sg);
#endif
/* XXX DISABLED, no users currently. If you wish to re-enable this
* XXX please determine whether the sync is to transfer ownership of
@ -972,6 +892,7 @@ void usb_buffer_dmasync_sg(const struct usb_device *dev, int is_in,
EXPORT_SYMBOL_GPL(usb_buffer_dmasync_sg);
#endif
#if 0
/**
* usb_buffer_unmap_sg - free DMA mapping(s) for a scatterlist
* @dev: device to which the scatterlist will be mapped
@ -997,6 +918,7 @@ void usb_buffer_unmap_sg(const struct usb_device *dev, int is_in,
is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
}
EXPORT_SYMBOL_GPL(usb_buffer_unmap_sg);
#endif
/* To disable USB, kernel command line is 'nousb' not 'usbcore.nousb' */
#ifdef MODULE

View File

@ -710,6 +710,43 @@ config USB_GADGETFS
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "gadgetfs".
config USB_FUNCTIONFS
tristate "Function Filesystem (EXPERIMENTAL)"
depends on EXPERIMENTAL
help
The Function Filesystem (FunctioFS) lets one create USB
composite functions in user space in the same way as GadgetFS
lets one create USB gadgets in user space. This allows creation
of composite gadgets such that some of the functions are
implemented in kernel space (for instance Ethernet, serial or
mass storage) and other are implemented in user space.
Say "y" to link the driver statically, or "m" to build
a dynamically linked module called "g_ffs".
config USB_FUNCTIONFS_ETH
bool "Include CDC ECM (Ethernet) function"
depends on USB_FUNCTIONFS && NET
help
Include an CDC ECM (Ethernet) funcion in the CDC ECM (Funcion)
Filesystem. If you also say "y" to the RNDIS query below the
gadget will have two configurations.
config USB_FUNCTIONFS_RNDIS
bool "Include RNDIS (Ethernet) function"
depends on USB_FUNCTIONFS && NET
help
Include an RNDIS (Ethernet) funcion in the Funcion Filesystem.
If you also say "y" to the CDC ECM query above the gadget will
have two configurations.
config USB_FUNCTIONFS_GENERIC
bool "Include 'pure' configuration"
depends on USB_FUNCTIONFS && (USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
help
Include a configuration with FunctionFS and no Ethernet
configuration.
config USB_FILE_STORAGE
tristate "File-backed Storage Gadget"
depends on BLOCK
@ -863,11 +900,30 @@ config USB_G_MULTI_CDC
If unsure, say "y".
config USB_G_HID
tristate "HID Gadget"
help
The HID gadget driver provides generic emulation of USB
Human Interface Devices (HID).
For more information, see Documentation/usb/gadget_hid.txt which
includes sample code for accessing the device files.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_hid".
# put drivers that need isochronous transfer support (for audio
# or video class gadget drivers), or specific hardware, here.
config USB_G_WEBCAM
tristate "USB Webcam Gadget"
depends on VIDEO_DEV
help
The Webcam Gadget acts as a composite USB Audio and Video Class
device. It provides a userspace API to process UVC control requests
and stream video data to the host.
# - none yet
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_webcam".
endchoice

View File

@ -20,7 +20,7 @@ obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
fsl_usb2_udc-objs := fsl_udc_core.o
ifeq ($(CONFIG_ARCH_MXC),y)
fsl_usb2_udc-objs += fsl_mx3_udc.o
fsl_usb2_udc-objs += fsl_mxc_udc.o
endif
obj-$(CONFIG_USB_M66592) += m66592-udc.o
obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o
@ -43,18 +43,24 @@ g_mass_storage-objs := mass_storage.o
g_printer-objs := printer.o
g_cdc-objs := cdc2.o
g_multi-objs := multi.o
g_hid-objs := hid.o
g_nokia-objs := nokia.o
g_webcam-objs := webcam.o
obj-$(CONFIG_USB_ZERO) += g_zero.o
obj-$(CONFIG_USB_AUDIO) += g_audio.o
obj-$(CONFIG_USB_ETH) += g_ether.o
obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
obj-$(CONFIG_USB_FUNCTIONFS) += g_ffs.o
obj-$(CONFIG_USB_ETH_FUNCTIONFS) += g_eth_ffs.o
obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
obj-$(CONFIG_USB_MASS_STORAGE) += g_mass_storage.o
obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
obj-$(CONFIG_USB_G_PRINTER) += g_printer.o
obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o
obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
obj-$(CONFIG_USB_G_HID) += g_hid.o
obj-$(CONFIG_USB_G_MULTI) += g_multi.o
obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o
obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o

View File

@ -48,10 +48,9 @@ static int queue_dbg_open(struct inode *inode, struct file *file)
spin_lock_irq(&ep->udc->lock);
list_for_each_entry(req, &ep->queue, queue) {
req_copy = kmalloc(sizeof(*req_copy), GFP_ATOMIC);
req_copy = kmemdup(req, sizeof(*req_copy), GFP_ATOMIC);
if (!req_copy)
goto fail;
memcpy(req_copy, req, sizeof(*req_copy));
list_add_tail(&req_copy->queue, queue_data);
}
spin_unlock_irq(&ep->udc->lock);

View File

@ -36,7 +36,7 @@
*/
/* big enough to hold our biggest descriptor */
#define USB_BUFSIZ 512
#define USB_BUFSIZ 1024
static struct usb_composite_driver *composite;
@ -85,7 +85,7 @@ MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
* This function returns the value of the function's bind(), which is
* zero for success else a negative errno value.
*/
int __init usb_add_function(struct usb_configuration *config,
int usb_add_function(struct usb_configuration *config,
struct usb_function *function)
{
int value = -EINVAL;
@ -215,7 +215,7 @@ int usb_function_activate(struct usb_function *function)
* Returns the interface ID which was allocated; or -ENODEV if no
* more interface IDs can be allocated.
*/
int __init usb_interface_id(struct usb_configuration *config,
int usb_interface_id(struct usb_configuration *config,
struct usb_function *function)
{
unsigned id = config->next_interface_id;
@ -480,7 +480,7 @@ done:
* assigns global resources including string IDs, and per-configuration
* resources such as interface IDs and endpoints.
*/
int __init usb_add_config(struct usb_composite_dev *cdev,
int usb_add_config(struct usb_composite_dev *cdev,
struct usb_configuration *config)
{
int status = -EINVAL;
@ -677,7 +677,7 @@ static int get_string(struct usb_composite_dev *cdev,
* ensure that for example different functions don't wrongly assign
* different meanings to the same identifier.
*/
int __init usb_string_id(struct usb_composite_dev *cdev)
int usb_string_id(struct usb_composite_dev *cdev)
{
if (cdev->next_string_id < 254) {
/* string id 0 is reserved */
@ -898,7 +898,19 @@ static void composite_disconnect(struct usb_gadget *gadget)
/*-------------------------------------------------------------------------*/
static void /* __init_or_exit */
static ssize_t composite_show_suspended(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct usb_gadget *gadget = dev_to_usb_gadget(dev);
struct usb_composite_dev *cdev = get_gadget_data(gadget);
return sprintf(buf, "%d\n", cdev->suspended);
}
static DEVICE_ATTR(suspended, 0444, composite_show_suspended, NULL);
static void
composite_unbind(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev = get_gadget_data(gadget);
@ -944,10 +956,11 @@ composite_unbind(struct usb_gadget *gadget)
}
kfree(cdev);
set_gadget_data(gadget, NULL);
device_remove_file(&gadget->dev, &dev_attr_suspended);
composite = NULL;
}
static void __init
static void
string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s)
{
struct usb_string *str = tab->strings;
@ -960,7 +973,7 @@ string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s)
}
}
static void __init
static void
string_override(struct usb_gadget_strings **tab, u8 id, const char *s)
{
while (*tab) {
@ -969,7 +982,7 @@ string_override(struct usb_gadget_strings **tab, u8 id, const char *s)
}
}
static int __init composite_bind(struct usb_gadget *gadget)
static int composite_bind(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev;
int status = -ENOMEM;
@ -1004,6 +1017,14 @@ static int __init composite_bind(struct usb_gadget *gadget)
*/
usb_ep_autoconfig_reset(cdev->gadget);
/* standardized runtime overrides for device ID data */
if (idVendor)
cdev->desc.idVendor = cpu_to_le16(idVendor);
if (idProduct)
cdev->desc.idProduct = cpu_to_le16(idProduct);
if (bcdDevice)
cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
/* composite gadget needs to assign strings for whole device (like
* serial number), register function drivers, potentially update
* power state and consumption, etc
@ -1015,14 +1036,6 @@ static int __init composite_bind(struct usb_gadget *gadget)
cdev->desc = *composite->dev;
cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
/* standardized runtime overrides for device ID data */
if (idVendor)
cdev->desc.idVendor = cpu_to_le16(idVendor);
if (idProduct)
cdev->desc.idProduct = cpu_to_le16(idProduct);
if (bcdDevice)
cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
/* strings can't be assigned before bind() allocates the
* releavnt identifiers
*/
@ -1036,6 +1049,10 @@ static int __init composite_bind(struct usb_gadget *gadget)
string_override(composite->strings,
cdev->desc.iSerialNumber, iSerialNumber);
status = device_create_file(&gadget->dev, &dev_attr_suspended);
if (status)
goto fail;
INFO(cdev, "%s ready\n", composite->name);
return 0;
@ -1064,6 +1081,8 @@ composite_suspend(struct usb_gadget *gadget)
}
if (composite->suspend)
composite->suspend(cdev);
cdev->suspended = 1;
}
static void
@ -1084,6 +1103,8 @@ composite_resume(struct usb_gadget *gadget)
f->resume(f);
}
}
cdev->suspended = 0;
}
/*-------------------------------------------------------------------------*/
@ -1092,7 +1113,6 @@ static struct usb_gadget_driver composite_driver = {
.speed = USB_SPEED_HIGH,
.bind = composite_bind,
/* .unbind = __exit_p(composite_unbind), */
.unbind = composite_unbind,
.setup = composite_setup,
@ -1121,7 +1141,7 @@ static struct usb_gadget_driver composite_driver = {
* while it was binding. That would usually be done in order to wait for
* some userspace participation.
*/
int __init usb_composite_register(struct usb_composite_driver *driver)
int usb_composite_register(struct usb_composite_driver *driver)
{
if (!driver || !driver->dev || !driver->bind || composite)
return -EINVAL;
@ -1142,7 +1162,7 @@ int __init usb_composite_register(struct usb_composite_driver *driver)
* This function is used to unregister drivers using the composite
* driver framework.
*/
void /* __exit */ usb_composite_unregister(struct usb_composite_driver *driver)
void usb_composite_unregister(struct usb_composite_driver *driver)
{
if (composite != driver)
return;

View File

@ -128,7 +128,7 @@ int usb_gadget_config_buf(
* with identifiers (for interfaces, strings, endpoints, and more)
* as needed by a given function instance.
*/
struct usb_descriptor_header **__init
struct usb_descriptor_header **
usb_copy_descriptors(struct usb_descriptor_header **src)
{
struct usb_descriptor_header **tmp;
@ -175,7 +175,7 @@ usb_copy_descriptors(struct usb_descriptor_header **src)
* intended use is to help remembering the endpoint descriptor to use
* when enabling a given endpoint.
*/
struct usb_endpoint_descriptor *__init
struct usb_endpoint_descriptor *
usb_find_endpoint(
struct usb_descriptor_header **src,
struct usb_descriptor_header **copy,

View File

@ -47,6 +47,7 @@
#include <linux/platform_device.h>
#include <linux/usb.h>
#include <linux/usb/gadget.h>
#include <linux/usb/hcd.h>
#include <asm/byteorder.h>
#include <asm/io.h>
@ -55,9 +56,6 @@
#include <asm/unaligned.h>
#include "../core/hcd.h"
#define DRIVER_DESC "USB Host+Gadget Emulator"
#define DRIVER_VERSION "02 May 2005"

View File

@ -34,12 +34,12 @@
/* we must assign addresses for configurable endpoints (like net2280) */
static __initdata unsigned epnum;
static unsigned epnum;
// #define MANY_ENDPOINTS
#ifdef MANY_ENDPOINTS
/* more than 15 configurable endpoints */
static __initdata unsigned in_epnum;
static unsigned in_epnum;
#endif
@ -59,7 +59,7 @@ static __initdata unsigned in_epnum;
* NOTE: each endpoint is unidirectional, as specified by its USB
* descriptor; and isn't specific to a configuration or altsetting.
*/
static int __init
static int
ep_matches (
struct usb_gadget *gadget,
struct usb_ep *ep,
@ -187,7 +187,7 @@ ep_matches (
return 1;
}
static struct usb_ep * __init
static struct usb_ep *
find_ep (struct usb_gadget *gadget, const char *name)
{
struct usb_ep *ep;
@ -229,7 +229,7 @@ find_ep (struct usb_gadget *gadget, const char *name)
*
* On failure, this returns a null endpoint descriptor.
*/
struct usb_ep * __init usb_ep_autoconfig (
struct usb_ep *usb_ep_autoconfig (
struct usb_gadget *gadget,
struct usb_endpoint_descriptor *desc
)
@ -304,7 +304,7 @@ struct usb_ep * __init usb_ep_autoconfig (
* state such as ep->driver_data and the record of assigned endpoints
* used by usb_ep_autoconfig().
*/
void __init usb_ep_autoconfig_reset (struct usb_gadget *gadget)
void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
{
struct usb_ep *ep;

View File

@ -116,7 +116,7 @@ acm_iad_descriptor = {
};
static struct usb_interface_descriptor acm_control_interface_desc __initdata = {
static struct usb_interface_descriptor acm_control_interface_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
@ -127,7 +127,7 @@ static struct usb_interface_descriptor acm_control_interface_desc __initdata = {
/* .iInterface = DYNAMIC */
};
static struct usb_interface_descriptor acm_data_interface_desc __initdata = {
static struct usb_interface_descriptor acm_data_interface_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
@ -138,7 +138,7 @@ static struct usb_interface_descriptor acm_data_interface_desc __initdata = {
/* .iInterface = DYNAMIC */
};
static struct usb_cdc_header_desc acm_header_desc __initdata = {
static struct usb_cdc_header_desc acm_header_desc = {
.bLength = sizeof(acm_header_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
@ -146,7 +146,7 @@ static struct usb_cdc_header_desc acm_header_desc __initdata = {
};
static struct usb_cdc_call_mgmt_descriptor
acm_call_mgmt_descriptor __initdata = {
acm_call_mgmt_descriptor = {
.bLength = sizeof(acm_call_mgmt_descriptor),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
@ -154,14 +154,14 @@ acm_call_mgmt_descriptor __initdata = {
/* .bDataInterface = DYNAMIC */
};
static struct usb_cdc_acm_descriptor acm_descriptor __initdata = {
static struct usb_cdc_acm_descriptor acm_descriptor = {
.bLength = sizeof(acm_descriptor),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_ACM_TYPE,
.bmCapabilities = USB_CDC_CAP_LINE,
};
static struct usb_cdc_union_desc acm_union_desc __initdata = {
static struct usb_cdc_union_desc acm_union_desc = {
.bLength = sizeof(acm_union_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_UNION_TYPE,
@ -171,7 +171,7 @@ static struct usb_cdc_union_desc acm_union_desc __initdata = {
/* full speed support: */
static struct usb_endpoint_descriptor acm_fs_notify_desc __initdata = {
static struct usb_endpoint_descriptor acm_fs_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
@ -180,21 +180,21 @@ static struct usb_endpoint_descriptor acm_fs_notify_desc __initdata = {
.bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL,
};
static struct usb_endpoint_descriptor acm_fs_in_desc __initdata = {
static struct usb_endpoint_descriptor acm_fs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_endpoint_descriptor acm_fs_out_desc __initdata = {
static struct usb_endpoint_descriptor acm_fs_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_descriptor_header *acm_fs_function[] __initdata = {
static struct usb_descriptor_header *acm_fs_function[] = {
(struct usb_descriptor_header *) &acm_iad_descriptor,
(struct usb_descriptor_header *) &acm_control_interface_desc,
(struct usb_descriptor_header *) &acm_header_desc,
@ -210,7 +210,7 @@ static struct usb_descriptor_header *acm_fs_function[] __initdata = {
/* high speed support: */
static struct usb_endpoint_descriptor acm_hs_notify_desc __initdata = {
static struct usb_endpoint_descriptor acm_hs_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
@ -219,21 +219,21 @@ static struct usb_endpoint_descriptor acm_hs_notify_desc __initdata = {
.bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
};
static struct usb_endpoint_descriptor acm_hs_in_desc __initdata = {
static struct usb_endpoint_descriptor acm_hs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = {
static struct usb_endpoint_descriptor acm_hs_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *acm_hs_function[] __initdata = {
static struct usb_descriptor_header *acm_hs_function[] = {
(struct usb_descriptor_header *) &acm_iad_descriptor,
(struct usb_descriptor_header *) &acm_control_interface_desc,
(struct usb_descriptor_header *) &acm_header_desc,
@ -571,7 +571,7 @@ static int acm_send_break(struct gserial *port, int duration)
/*-------------------------------------------------------------------------*/
/* ACM function driver setup/binding */
static int __init
static int
acm_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
@ -719,7 +719,7 @@ static inline bool can_support_cdc(struct usb_configuration *c)
* handle all the ones it binds. Caller is also responsible
* for calling @gserial_cleanup() before module unload.
*/
int __init acm_bind_config(struct usb_configuration *c, u8 port_num)
int acm_bind_config(struct usb_configuration *c, u8 port_num)
{
struct f_acm *acm;
int status;

View File

@ -113,7 +113,7 @@ static inline unsigned ecm_bitrate(struct usb_gadget *g)
/* interface descriptor: */
static struct usb_interface_descriptor ecm_control_intf __initdata = {
static struct usb_interface_descriptor ecm_control_intf = {
.bLength = sizeof ecm_control_intf,
.bDescriptorType = USB_DT_INTERFACE,
@ -126,7 +126,7 @@ static struct usb_interface_descriptor ecm_control_intf __initdata = {
/* .iInterface = DYNAMIC */
};
static struct usb_cdc_header_desc ecm_header_desc __initdata = {
static struct usb_cdc_header_desc ecm_header_desc = {
.bLength = sizeof ecm_header_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
@ -134,7 +134,7 @@ static struct usb_cdc_header_desc ecm_header_desc __initdata = {
.bcdCDC = cpu_to_le16(0x0110),
};
static struct usb_cdc_union_desc ecm_union_desc __initdata = {
static struct usb_cdc_union_desc ecm_union_desc = {
.bLength = sizeof(ecm_union_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_UNION_TYPE,
@ -142,7 +142,7 @@ static struct usb_cdc_union_desc ecm_union_desc __initdata = {
/* .bSlaveInterface0 = DYNAMIC */
};
static struct usb_cdc_ether_desc ecm_desc __initdata = {
static struct usb_cdc_ether_desc ecm_desc = {
.bLength = sizeof ecm_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_ETHERNET_TYPE,
@ -157,7 +157,7 @@ static struct usb_cdc_ether_desc ecm_desc __initdata = {
/* the default data interface has no endpoints ... */
static struct usb_interface_descriptor ecm_data_nop_intf __initdata = {
static struct usb_interface_descriptor ecm_data_nop_intf = {
.bLength = sizeof ecm_data_nop_intf,
.bDescriptorType = USB_DT_INTERFACE,
@ -172,7 +172,7 @@ static struct usb_interface_descriptor ecm_data_nop_intf __initdata = {
/* ... but the "real" data interface has two bulk endpoints */
static struct usb_interface_descriptor ecm_data_intf __initdata = {
static struct usb_interface_descriptor ecm_data_intf = {
.bLength = sizeof ecm_data_intf,
.bDescriptorType = USB_DT_INTERFACE,
@ -187,7 +187,7 @@ static struct usb_interface_descriptor ecm_data_intf __initdata = {
/* full speed support: */
static struct usb_endpoint_descriptor fs_ecm_notify_desc __initdata = {
static struct usb_endpoint_descriptor fs_ecm_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -197,7 +197,7 @@ static struct usb_endpoint_descriptor fs_ecm_notify_desc __initdata = {
.bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
};
static struct usb_endpoint_descriptor fs_ecm_in_desc __initdata = {
static struct usb_endpoint_descriptor fs_ecm_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -205,7 +205,7 @@ static struct usb_endpoint_descriptor fs_ecm_in_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_endpoint_descriptor fs_ecm_out_desc __initdata = {
static struct usb_endpoint_descriptor fs_ecm_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -213,7 +213,7 @@ static struct usb_endpoint_descriptor fs_ecm_out_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_descriptor_header *ecm_fs_function[] __initdata = {
static struct usb_descriptor_header *ecm_fs_function[] = {
/* CDC ECM control descriptors */
(struct usb_descriptor_header *) &ecm_control_intf,
(struct usb_descriptor_header *) &ecm_header_desc,
@ -231,7 +231,7 @@ static struct usb_descriptor_header *ecm_fs_function[] __initdata = {
/* high speed support: */
static struct usb_endpoint_descriptor hs_ecm_notify_desc __initdata = {
static struct usb_endpoint_descriptor hs_ecm_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -240,7 +240,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};
static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = {
static struct usb_endpoint_descriptor hs_ecm_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -249,7 +249,7 @@ static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = {
static struct usb_endpoint_descriptor hs_ecm_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -258,7 +258,7 @@ static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *ecm_hs_function[] __initdata = {
static struct usb_descriptor_header *ecm_hs_function[] = {
/* CDC ECM control descriptors */
(struct usb_descriptor_header *) &ecm_control_intf,
(struct usb_descriptor_header *) &ecm_header_desc,
@ -597,7 +597,7 @@ static void ecm_close(struct gether *geth)
/* ethernet function driver setup/binding */
static int __init
static int
ecm_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
@ -763,7 +763,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
* Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload.
*/
int __init ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
int
ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
{
struct f_ecm *ecm;
int status;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,673 @@
/*
* f_hid.c -- USB HID function driver
*
* Copyright (C) 2010 Fabien Chouteau <fabien.chouteau@barco.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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/utsname.h>
#include <linux/module.h>
#include <linux/hid.h>
#include <linux/cdev.h>
#include <linux/mutex.h>
#include <linux/poll.h>
#include <linux/smp_lock.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
#include <linux/usb/g_hid.h>
static int major, minors;
static struct class *hidg_class;
/*-------------------------------------------------------------------------*/
/* HID gadget struct */
struct f_hidg {
/* configuration */
unsigned char bInterfaceSubClass;
unsigned char bInterfaceProtocol;
unsigned short report_desc_length;
char *report_desc;
unsigned short report_length;
/* recv report */
char *set_report_buff;
unsigned short set_report_length;
spinlock_t spinlock;
wait_queue_head_t read_queue;
/* send report */
struct mutex lock;
bool write_pending;
wait_queue_head_t write_queue;
struct usb_request *req;
int minor;
struct cdev cdev;
struct usb_function func;
struct usb_ep *in_ep;
struct usb_endpoint_descriptor *fs_in_ep_desc;
struct usb_endpoint_descriptor *hs_in_ep_desc;
};
static inline struct f_hidg *func_to_hidg(struct usb_function *f)
{
return container_of(f, struct f_hidg, func);
}
/*-------------------------------------------------------------------------*/
/* Static descriptors */
static struct usb_interface_descriptor hidg_interface_desc = {
.bLength = sizeof hidg_interface_desc,
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_HID,
/* .bInterfaceSubClass = DYNAMIC */
/* .bInterfaceProtocol = DYNAMIC */
/* .iInterface = DYNAMIC */
};
static struct hid_descriptor hidg_desc = {
.bLength = sizeof hidg_desc,
.bDescriptorType = HID_DT_HID,
.bcdHID = 0x0101,
.bCountryCode = 0x00,
.bNumDescriptors = 0x1,
/*.desc[0].bDescriptorType = DYNAMIC */
/*.desc[0].wDescriptorLenght = DYNAMIC */
};
/* High-Speed Support */
static struct usb_endpoint_descriptor hidg_hs_in_ep_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
/*.wMaxPacketSize = DYNAMIC */
.bInterval = 4, /* FIXME: Add this field in the
* HID gadget configuration?
* (struct hidg_func_descriptor)
*/
};
static struct usb_descriptor_header *hidg_hs_descriptors[] = {
(struct usb_descriptor_header *)&hidg_interface_desc,
(struct usb_descriptor_header *)&hidg_desc,
(struct usb_descriptor_header *)&hidg_hs_in_ep_desc,
NULL,
};
/* Full-Speed Support */
static struct usb_endpoint_descriptor hidg_fs_in_ep_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
/*.wMaxPacketSize = DYNAMIC */
.bInterval = 10, /* FIXME: Add this field in the
* HID gadget configuration?
* (struct hidg_func_descriptor)
*/
};
static struct usb_descriptor_header *hidg_fs_descriptors[] = {
(struct usb_descriptor_header *)&hidg_interface_desc,
(struct usb_descriptor_header *)&hidg_desc,
(struct usb_descriptor_header *)&hidg_fs_in_ep_desc,
NULL,
};
/*-------------------------------------------------------------------------*/
/* Char Device */
static ssize_t f_hidg_read(struct file *file, char __user *buffer,
size_t count, loff_t *ptr)
{
struct f_hidg *hidg = (struct f_hidg *)file->private_data;
char *tmp_buff = NULL;
unsigned long flags;
if (!count)
return 0;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
spin_lock_irqsave(&hidg->spinlock, flags);
#define READ_COND (hidg->set_report_buff != NULL)
while (!READ_COND) {
spin_unlock_irqrestore(&hidg->spinlock, flags);
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
if (wait_event_interruptible(hidg->read_queue, READ_COND))
return -ERESTARTSYS;
spin_lock_irqsave(&hidg->spinlock, flags);
}
count = min_t(unsigned, count, hidg->set_report_length);
tmp_buff = hidg->set_report_buff;
hidg->set_report_buff = NULL;
spin_unlock_irqrestore(&hidg->spinlock, flags);
if (tmp_buff != NULL) {
/* copy to user outside spinlock */
count -= copy_to_user(buffer, tmp_buff, count);
kfree(tmp_buff);
} else
count = -ENOMEM;
return count;
}
static void f_hidg_req_complete(struct usb_ep *ep, struct usb_request *req)
{
struct f_hidg *hidg = (struct f_hidg *)ep->driver_data;
if (req->status != 0) {
ERROR(hidg->func.config->cdev,
"End Point Request ERROR: %d\n", req->status);
}
hidg->write_pending = 0;
wake_up(&hidg->write_queue);
}
static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
size_t count, loff_t *offp)
{
struct f_hidg *hidg = (struct f_hidg *)file->private_data;
ssize_t status = -ENOMEM;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
mutex_lock(&hidg->lock);
#define WRITE_COND (!hidg->write_pending)
/* write queue */
while (!WRITE_COND) {
mutex_unlock(&hidg->lock);
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
if (wait_event_interruptible_exclusive(
hidg->write_queue, WRITE_COND))
return -ERESTARTSYS;
mutex_lock(&hidg->lock);
}
count = min_t(unsigned, count, hidg->report_length);
status = copy_from_user(hidg->req->buf, buffer, count);
if (status != 0) {
ERROR(hidg->func.config->cdev,
"copy_from_user error\n");
mutex_unlock(&hidg->lock);
return -EINVAL;
}
hidg->req->status = 0;
hidg->req->zero = 0;
hidg->req->length = count;
hidg->req->complete = f_hidg_req_complete;
hidg->req->context = hidg;
hidg->write_pending = 1;
status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC);
if (status < 0) {
ERROR(hidg->func.config->cdev,
"usb_ep_queue error on int endpoint %zd\n", status);
hidg->write_pending = 0;
wake_up(&hidg->write_queue);
} else {
status = count;
}
mutex_unlock(&hidg->lock);
return status;
}
static unsigned int f_hidg_poll(struct file *file, poll_table *wait)
{
struct f_hidg *hidg = (struct f_hidg *)file->private_data;
unsigned int ret = 0;
poll_wait(file, &hidg->read_queue, wait);
poll_wait(file, &hidg->write_queue, wait);
if (WRITE_COND)
ret |= POLLOUT | POLLWRNORM;
if (READ_COND)
ret |= POLLIN | POLLRDNORM;
return ret;
}
#undef WRITE_COND
#undef READ_COND
static int f_hidg_release(struct inode *inode, struct file *fd)
{
fd->private_data = NULL;
return 0;
}
static int f_hidg_open(struct inode *inode, struct file *fd)
{
struct f_hidg *hidg =
container_of(inode->i_cdev, struct f_hidg, cdev);
fd->private_data = hidg;
return 0;
}
/*-------------------------------------------------------------------------*/
/* usb_function */
static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req)
{
struct f_hidg *hidg = (struct f_hidg *)req->context;
if (req->status != 0 || req->buf == NULL || req->actual == 0) {
ERROR(hidg->func.config->cdev, "%s FAILED\n", __func__);
return;
}
spin_lock(&hidg->spinlock);
hidg->set_report_buff = krealloc(hidg->set_report_buff,
req->actual, GFP_ATOMIC);
if (hidg->set_report_buff == NULL) {
spin_unlock(&hidg->spinlock);
return;
}
hidg->set_report_length = req->actual;
memcpy(hidg->set_report_buff, req->buf, req->actual);
spin_unlock(&hidg->spinlock);
wake_up(&hidg->read_queue);
return;
}
static int hidg_setup(struct usb_function *f,
const struct usb_ctrlrequest *ctrl)
{
struct f_hidg *hidg = func_to_hidg(f);
struct usb_composite_dev *cdev = f->config->cdev;
struct usb_request *req = cdev->req;
int status = 0;
__u16 value, length;
value = __le16_to_cpu(ctrl->wValue);
length = __le16_to_cpu(ctrl->wLength);
VDBG(cdev, "hid_setup crtl_request : bRequestType:0x%x bRequest:0x%x "
"Value:0x%x\n", ctrl->bRequestType, ctrl->bRequest, value);
switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_GET_REPORT):
VDBG(cdev, "get_report\n");
/* send an empty report */
length = min_t(unsigned, length, hidg->report_length);
memset(req->buf, 0x0, length);
goto respond;
break;
case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_GET_PROTOCOL):
VDBG(cdev, "get_protocol\n");
goto stall;
break;
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_SET_REPORT):
VDBG(cdev, "set_report | wLenght=%d\n", ctrl->wLength);
req->context = hidg;
req->complete = hidg_set_report_complete;
goto respond;
break;
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_SET_PROTOCOL):
VDBG(cdev, "set_protocol\n");
goto stall;
break;
case ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8
| USB_REQ_GET_DESCRIPTOR):
switch (value >> 8) {
case HID_DT_REPORT:
VDBG(cdev, "USB_REQ_GET_DESCRIPTOR: REPORT\n");
length = min_t(unsigned short, length,
hidg->report_desc_length);
memcpy(req->buf, hidg->report_desc, length);
goto respond;
break;
default:
VDBG(cdev, "Unknown decriptor request 0x%x\n",
value >> 8);
goto stall;
break;
}
break;
default:
VDBG(cdev, "Unknown request 0x%x\n",
ctrl->bRequest);
goto stall;
break;
}
stall:
return -EOPNOTSUPP;
respond:
req->zero = 0;
req->length = length;
status = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
if (status < 0)
ERROR(cdev, "usb_ep_queue error on ep0 %d\n", value);
return status;
}
static void hidg_disable(struct usb_function *f)
{
struct f_hidg *hidg = func_to_hidg(f);
usb_ep_disable(hidg->in_ep);
hidg->in_ep->driver_data = NULL;
return;
}
static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct usb_composite_dev *cdev = f->config->cdev;
struct f_hidg *hidg = func_to_hidg(f);
const struct usb_endpoint_descriptor *ep_desc;
int status = 0;
VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt);
if (hidg->in_ep != NULL) {
/* restart endpoint */
if (hidg->in_ep->driver_data != NULL)
usb_ep_disable(hidg->in_ep);
ep_desc = ep_choose(f->config->cdev->gadget,
hidg->hs_in_ep_desc, hidg->fs_in_ep_desc);
status = usb_ep_enable(hidg->in_ep, ep_desc);
if (status < 0) {
ERROR(cdev, "Enable endpoint FAILED!\n");
goto fail;
}
hidg->in_ep->driver_data = hidg;
}
fail:
return status;
}
const struct file_operations f_hidg_fops = {
.owner = THIS_MODULE,
.open = f_hidg_open,
.release = f_hidg_release,
.write = f_hidg_write,
.read = f_hidg_read,
.poll = f_hidg_poll,
};
static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_ep *ep;
struct f_hidg *hidg = func_to_hidg(f);
int status;
dev_t dev;
/* allocate instance-specific interface IDs, and patch descriptors */
status = usb_interface_id(c, f);
if (status < 0)
goto fail;
hidg_interface_desc.bInterfaceNumber = status;
/* allocate instance-specific endpoints */
status = -ENODEV;
ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc);
if (!ep)
goto fail;
ep->driver_data = c->cdev; /* claim */
hidg->in_ep = ep;
/* preallocate request and buffer */
status = -ENOMEM;
hidg->req = usb_ep_alloc_request(hidg->in_ep, GFP_KERNEL);
if (!hidg->req)
goto fail;
hidg->req->buf = kmalloc(hidg->report_length, GFP_KERNEL);
if (!hidg->req->buf)
goto fail;
/* set descriptor dynamic values */
hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass;
hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
hidg_hs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
hidg_desc.desc[0].bDescriptorType = HID_DT_REPORT;
hidg_desc.desc[0].wDescriptorLength =
cpu_to_le16(hidg->report_desc_length);
hidg->set_report_buff = NULL;
/* copy descriptors */
f->descriptors = usb_copy_descriptors(hidg_fs_descriptors);
if (!f->descriptors)
goto fail;
hidg->fs_in_ep_desc = usb_find_endpoint(hidg_fs_descriptors,
f->descriptors,
&hidg_fs_in_ep_desc);
if (gadget_is_dualspeed(c->cdev->gadget)) {
hidg_hs_in_ep_desc.bEndpointAddress =
hidg_fs_in_ep_desc.bEndpointAddress;
f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors);
if (!f->hs_descriptors)
goto fail;
hidg->hs_in_ep_desc = usb_find_endpoint(hidg_hs_descriptors,
f->hs_descriptors,
&hidg_hs_in_ep_desc);
} else {
hidg->hs_in_ep_desc = NULL;
}
mutex_init(&hidg->lock);
spin_lock_init(&hidg->spinlock);
init_waitqueue_head(&hidg->write_queue);
init_waitqueue_head(&hidg->read_queue);
/* create char device */
cdev_init(&hidg->cdev, &f_hidg_fops);
dev = MKDEV(major, hidg->minor);
status = cdev_add(&hidg->cdev, dev, 1);
if (status)
goto fail;
device_create(hidg_class, NULL, dev, NULL, "%s%d", "hidg", hidg->minor);
return 0;
fail:
ERROR(f->config->cdev, "hidg_bind FAILED\n");
if (hidg->req != NULL) {
kfree(hidg->req->buf);
if (hidg->in_ep != NULL)
usb_ep_free_request(hidg->in_ep, hidg->req);
}
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
return status;
}
static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_hidg *hidg = func_to_hidg(f);
device_destroy(hidg_class, MKDEV(major, hidg->minor));
cdev_del(&hidg->cdev);
/* disable/free request and end point */
usb_ep_disable(hidg->in_ep);
usb_ep_dequeue(hidg->in_ep, hidg->req);
kfree(hidg->req->buf);
usb_ep_free_request(hidg->in_ep, hidg->req);
/* free descriptors copies */
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
kfree(hidg->report_desc);
kfree(hidg->set_report_buff);
kfree(hidg);
}
/*-------------------------------------------------------------------------*/
/* Strings */
#define CT_FUNC_HID_IDX 0
static struct usb_string ct_func_string_defs[] = {
[CT_FUNC_HID_IDX].s = "HID Interface",
{}, /* end of list */
};
static struct usb_gadget_strings ct_func_string_table = {
.language = 0x0409, /* en-US */
.strings = ct_func_string_defs,
};
static struct usb_gadget_strings *ct_func_strings[] = {
&ct_func_string_table,
NULL,
};
/*-------------------------------------------------------------------------*/
/* usb_configuration */
int __init hidg_bind_config(struct usb_configuration *c,
struct hidg_func_descriptor *fdesc, int index)
{
struct f_hidg *hidg;
int status;
if (index >= minors)
return -ENOENT;
/* maybe allocate device-global string IDs, and patch descriptors */
if (ct_func_string_defs[CT_FUNC_HID_IDX].id == 0) {
status = usb_string_id(c->cdev);
if (status < 0)
return status;
ct_func_string_defs[CT_FUNC_HID_IDX].id = status;
hidg_interface_desc.iInterface = status;
}
/* allocate and initialize one new instance */
hidg = kzalloc(sizeof *hidg, GFP_KERNEL);
if (!hidg)
return -ENOMEM;
hidg->minor = index;
hidg->bInterfaceSubClass = fdesc->subclass;
hidg->bInterfaceProtocol = fdesc->protocol;
hidg->report_length = fdesc->report_length;
hidg->report_desc_length = fdesc->report_desc_length;
hidg->report_desc = kmemdup(fdesc->report_desc,
fdesc->report_desc_length,
GFP_KERNEL);
if (!hidg->report_desc) {
kfree(hidg);
return -ENOMEM;
}
hidg->func.name = "hid";
hidg->func.strings = ct_func_strings;
hidg->func.bind = hidg_bind;
hidg->func.unbind = hidg_unbind;
hidg->func.set_alt = hidg_set_alt;
hidg->func.disable = hidg_disable;
hidg->func.setup = hidg_setup;
status = usb_add_function(c, &hidg->func);
if (status)
kfree(hidg);
return status;
}
int __init ghid_setup(struct usb_gadget *g, int count)
{
int status;
dev_t dev;
hidg_class = class_create(THIS_MODULE, "hidg");
status = alloc_chrdev_region(&dev, 0, count, "hidg");
if (!status) {
major = MAJOR(dev);
minors = count;
}
return status;
}
void ghid_cleanup(void)
{
if (major) {
unregister_chrdev_region(MKDEV(major, 0), minors);
major = minors = 0;
}
class_destroy(hidg_class);
hidg_class = NULL;
}

View File

@ -163,6 +163,10 @@
* ro setting are not allowed when the medium is loaded or if CD-ROM
* emulation is being used.
*
* When a LUN receive an "eject" SCSI request (Start/Stop Unit),
* if the LUN is removable, the backing file is released to simulate
* ejection.
*
*
* This function is heavily based on "File-backed Storage Gadget" by
* Alan Stern which in turn is heavily based on "Gadget Zero" by David
@ -302,7 +306,6 @@ static const char fsg_string_interface[] = "Mass Storage";
#define FSG_NO_INTR_EP 1
#define FSG_BUFFHD_STATIC_BUFFER 1
#define FSG_NO_DEVICE_STRINGS 1
#define FSG_NO_OTG 1
#define FSG_NO_INTR_EP 1
@ -1385,12 +1388,50 @@ static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh)
static int do_start_stop(struct fsg_common *common)
{
if (!common->curlun) {
struct fsg_lun *curlun = common->curlun;
int loej, start;
if (!curlun) {
return -EINVAL;
} else if (!common->curlun->removable) {
common->curlun->sense_data = SS_INVALID_COMMAND;
} else if (!curlun->removable) {
curlun->sense_data = SS_INVALID_COMMAND;
return -EINVAL;
}
loej = common->cmnd[4] & 0x02;
start = common->cmnd[4] & 0x01;
/* eject code from file_storage.c:do_start_stop() */
if ((common->cmnd[1] & ~0x01) != 0 || /* Mask away Immed */
(common->cmnd[4] & ~0x03) != 0) { /* Mask LoEj, Start */
curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL;
}
if (!start) {
/* Are we allowed to unload the media? */
if (curlun->prevent_medium_removal) {
LDBG(curlun, "unload attempt prevented\n");
curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
return -EINVAL;
}
if (loej) { /* Simulate an unload/eject */
up_read(&common->filesem);
down_write(&common->filesem);
fsg_lun_close(curlun);
up_write(&common->filesem);
down_read(&common->filesem);
}
} else {
/* Our emulation doesn't support mounting; the medium is
* available for use as soon as it is loaded. */
if (!fsg_lun_is_open(curlun)) {
curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
return -EINVAL;
}
}
return 0;
}
@ -2701,10 +2742,8 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
/* Maybe allocate device-global string IDs, and patch descriptors */
if (fsg_strings[FSG_STRING_INTERFACE].id == 0) {
rc = usb_string_id(cdev);
if (rc < 0) {
kfree(common);
return ERR_PTR(rc);
}
if (unlikely(rc < 0))
goto error_release;
fsg_strings[FSG_STRING_INTERFACE].id = rc;
fsg_intf_desc.iInterface = rc;
}
@ -2712,9 +2751,9 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
/* Create the LUNs, open their backing files, and register the
* LUN devices in sysfs. */
curlun = kzalloc(nluns * sizeof *curlun, GFP_KERNEL);
if (!curlun) {
kfree(common);
return ERR_PTR(-ENOMEM);
if (unlikely(!curlun)) {
rc = -ENOMEM;
goto error_release;
}
common->luns = curlun;
@ -2762,13 +2801,19 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
/* Data buffers cyclic list */
/* Buffers in buffhds are static -- no need for additional
* allocation. */
bh = common->buffhds;
i = FSG_NUM_BUFFERS - 1;
i = FSG_NUM_BUFFERS;
goto buffhds_first_it;
do {
bh->next = bh + 1;
} while (++bh, --i);
++bh;
buffhds_first_it:
bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL);
if (unlikely(!bh->buf)) {
rc = -ENOMEM;
goto error_release;
}
} while (--i);
bh->next = common->buffhds;
@ -2867,10 +2912,7 @@ error_release:
static void fsg_common_release(struct kref *ref)
{
struct fsg_common *common =
container_of(ref, struct fsg_common, ref);
unsigned i = common->nluns;
struct fsg_lun *lun = common->luns;
struct fsg_common *common = container_of(ref, struct fsg_common, ref);
/* If the thread isn't already dead, tell it to exit now */
if (common->state != FSG_STATE_TERMINATED) {
@ -2881,17 +2923,29 @@ static void fsg_common_release(struct kref *ref)
complete(&common->thread_notifier);
}
/* Beware tempting for -> do-while optimization: when in error
* recovery nluns may be zero. */
if (likely(common->luns)) {
struct fsg_lun *lun = common->luns;
unsigned i = common->nluns;
for (; i; --i, ++lun) {
device_remove_file(&lun->dev, &dev_attr_ro);
device_remove_file(&lun->dev, &dev_attr_file);
fsg_lun_close(lun);
device_unregister(&lun->dev);
/* In error recovery common->nluns may be zero. */
for (; i; --i, ++lun) {
device_remove_file(&lun->dev, &dev_attr_ro);
device_remove_file(&lun->dev, &dev_attr_file);
fsg_lun_close(lun);
device_unregister(&lun->dev);
}
kfree(common->luns);
}
{
struct fsg_buffhd *bh = common->buffhds;
unsigned i = FSG_NUM_BUFFERS;
do {
kfree(bh->buf);
} while (++bh, --i);
}
kfree(common->luns);
if (common->free_storage_on_release)
kfree(common);
}
@ -2906,11 +2960,13 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
DBG(fsg, "unbind\n");
fsg_common_put(fsg->common);
usb_free_descriptors(fsg->function.descriptors);
usb_free_descriptors(fsg->function.hs_descriptors);
kfree(fsg);
}
static int __init fsg_bind(struct usb_configuration *c, struct usb_function *f)
static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
struct usb_gadget *gadget = c->cdev->gadget;
@ -2946,7 +3002,9 @@ static int __init fsg_bind(struct usb_configuration *c, struct usb_function *f)
fsg_fs_bulk_in_desc.bEndpointAddress;
fsg_hs_bulk_out_desc.bEndpointAddress =
fsg_fs_bulk_out_desc.bEndpointAddress;
f->hs_descriptors = fsg_hs_function;
f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
if (unlikely(!f->hs_descriptors))
return -ENOMEM;
}
return 0;
@ -2978,7 +3036,11 @@ static int fsg_add(struct usb_composite_dev *cdev,
fsg->function.name = FSG_DRIVER_DESC;
fsg->function.strings = fsg_strings_array;
fsg->function.descriptors = fsg_fs_function;
fsg->function.descriptors = usb_copy_descriptors(fsg_fs_function);
if (unlikely(!fsg->function.descriptors)) {
rc = -ENOMEM;
goto error_free_fsg;
}
fsg->function.bind = fsg_bind;
fsg->function.unbind = fsg_unbind;
fsg->function.setup = fsg_setup;
@ -2993,11 +3055,19 @@ static int fsg_add(struct usb_composite_dev *cdev,
* call to usb_add_function() was successful. */
rc = usb_add_function(c, &fsg->function);
if (unlikely(rc))
goto error_free_all;
if (likely(rc == 0))
fsg_common_get(fsg->common);
else
kfree(fsg);
fsg_common_get(fsg->common);
return 0;
error_free_all:
usb_free_descriptors(fsg->function.descriptors);
/* fsg_bind() might have copied those; or maybe not? who cares
* -- free it just in case. */
usb_free_descriptors(fsg->function.hs_descriptors);
error_free_fsg:
kfree(fsg);
return rc;
}

View File

@ -122,7 +122,7 @@ static unsigned int bitrate(struct usb_gadget *g)
/* interface descriptor: */
static struct usb_interface_descriptor rndis_control_intf __initdata = {
static struct usb_interface_descriptor rndis_control_intf = {
.bLength = sizeof rndis_control_intf,
.bDescriptorType = USB_DT_INTERFACE,
@ -135,7 +135,7 @@ static struct usb_interface_descriptor rndis_control_intf __initdata = {
/* .iInterface = DYNAMIC */
};
static struct usb_cdc_header_desc header_desc __initdata = {
static struct usb_cdc_header_desc header_desc = {
.bLength = sizeof header_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
@ -143,7 +143,7 @@ static struct usb_cdc_header_desc header_desc __initdata = {
.bcdCDC = cpu_to_le16(0x0110),
};
static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = {
static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = {
.bLength = sizeof call_mgmt_descriptor,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
@ -152,7 +152,7 @@ static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = {
.bDataInterface = 0x01,
};
static struct usb_cdc_acm_descriptor rndis_acm_descriptor __initdata = {
static struct usb_cdc_acm_descriptor rndis_acm_descriptor = {
.bLength = sizeof rndis_acm_descriptor,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_ACM_TYPE,
@ -160,7 +160,7 @@ static struct usb_cdc_acm_descriptor rndis_acm_descriptor __initdata = {
.bmCapabilities = 0x00,
};
static struct usb_cdc_union_desc rndis_union_desc __initdata = {
static struct usb_cdc_union_desc rndis_union_desc = {
.bLength = sizeof(rndis_union_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_UNION_TYPE,
@ -170,7 +170,7 @@ static struct usb_cdc_union_desc rndis_union_desc __initdata = {
/* the data interface has two bulk endpoints */
static struct usb_interface_descriptor rndis_data_intf __initdata = {
static struct usb_interface_descriptor rndis_data_intf = {
.bLength = sizeof rndis_data_intf,
.bDescriptorType = USB_DT_INTERFACE,
@ -198,7 +198,7 @@ rndis_iad_descriptor = {
/* full speed support: */
static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
static struct usb_endpoint_descriptor fs_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -208,7 +208,7 @@ static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
.bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
};
static struct usb_endpoint_descriptor fs_in_desc __initdata = {
static struct usb_endpoint_descriptor fs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -216,7 +216,7 @@ static struct usb_endpoint_descriptor fs_in_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_endpoint_descriptor fs_out_desc __initdata = {
static struct usb_endpoint_descriptor fs_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -224,7 +224,7 @@ static struct usb_endpoint_descriptor fs_out_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_descriptor_header *eth_fs_function[] __initdata = {
static struct usb_descriptor_header *eth_fs_function[] = {
(struct usb_descriptor_header *) &rndis_iad_descriptor,
/* control interface matches ACM, not Ethernet */
(struct usb_descriptor_header *) &rndis_control_intf,
@ -242,7 +242,7 @@ static struct usb_descriptor_header *eth_fs_function[] __initdata = {
/* high speed support: */
static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
static struct usb_endpoint_descriptor hs_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -251,7 +251,7 @@ static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};
static struct usb_endpoint_descriptor hs_in_desc __initdata = {
static struct usb_endpoint_descriptor hs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -260,7 +260,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor hs_out_desc __initdata = {
static struct usb_endpoint_descriptor hs_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -269,7 +269,7 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *eth_hs_function[] __initdata = {
static struct usb_descriptor_header *eth_hs_function[] = {
(struct usb_descriptor_header *) &rndis_iad_descriptor,
/* control interface matches ACM, not Ethernet */
(struct usb_descriptor_header *) &rndis_control_intf,
@ -594,7 +594,7 @@ static void rndis_close(struct gether *geth)
/* ethernet function driver setup/binding */
static int __init
static int
rndis_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
@ -786,7 +786,8 @@ static inline bool can_support_rndis(struct usb_configuration *c)
* Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload.
*/
int __init rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
int
rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
{
struct f_rndis *rndis;
int status;

View File

@ -0,0 +1,661 @@
/*
* uvc_gadget.c -- USB Video Class Gadget driver
*
* Copyright (C) 2009-2010
* Laurent Pinchart (laurent.pinchart@ideasonboard.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.
*
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/video.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-event.h>
#include "uvc.h"
unsigned int uvc_trace_param;
/* --------------------------------------------------------------------------
* Function descriptors
*/
/* string IDs are assigned dynamically */
#define UVC_STRING_ASSOCIATION_IDX 0
#define UVC_STRING_CONTROL_IDX 1
#define UVC_STRING_STREAMING_IDX 2
static struct usb_string uvc_en_us_strings[] = {
[UVC_STRING_ASSOCIATION_IDX].s = "UVC Camera",
[UVC_STRING_CONTROL_IDX].s = "Video Control",
[UVC_STRING_STREAMING_IDX].s = "Video Streaming",
{ }
};
static struct usb_gadget_strings uvc_stringtab = {
.language = 0x0409, /* en-us */
.strings = uvc_en_us_strings,
};
static struct usb_gadget_strings *uvc_function_strings[] = {
&uvc_stringtab,
NULL,
};
#define UVC_INTF_VIDEO_CONTROL 0
#define UVC_INTF_VIDEO_STREAMING 1
static struct usb_interface_assoc_descriptor uvc_iad __initdata = {
.bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
.bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
.bFirstInterface = 0,
.bInterfaceCount = 2,
.bFunctionClass = USB_CLASS_VIDEO,
.bFunctionSubClass = 0x03,
.bFunctionProtocol = 0x00,
.iFunction = 0,
};
static struct usb_interface_descriptor uvc_control_intf __initdata = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = UVC_INTF_VIDEO_CONTROL,
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x00,
.iInterface = 0,
};
static struct usb_endpoint_descriptor uvc_control_ep __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(16),
.bInterval = 8,
};
static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = {
.bLength = UVC_DT_CONTROL_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_CS_ENDPOINT,
.bDescriptorSubType = UVC_EP_INTERRUPT,
.wMaxTransferSize = cpu_to_le16(16),
};
static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = UVC_INTF_VIDEO_STREAMING,
.bAlternateSetting = 0,
.bNumEndpoints = 0,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 0x02,
.bInterfaceProtocol = 0x00,
.iInterface = 0,
};
static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = UVC_INTF_VIDEO_STREAMING,
.bAlternateSetting = 1,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 0x02,
.bInterfaceProtocol = 0x00,
.iInterface = 0,
};
static struct usb_endpoint_descriptor uvc_streaming_ep = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = cpu_to_le16(512),
.bInterval = 1,
};
static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
(struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
(struct usb_descriptor_header *) &uvc_streaming_ep,
NULL,
};
static const struct usb_descriptor_header * const uvc_hs_streaming[] = {
(struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
(struct usb_descriptor_header *) &uvc_streaming_ep,
NULL,
};
/* --------------------------------------------------------------------------
* Control requests
*/
static void
uvc_function_ep0_complete(struct usb_ep *ep, struct usb_request *req)
{
struct uvc_device *uvc = req->context;
struct v4l2_event v4l2_event;
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
if (uvc->event_setup_out) {
uvc->event_setup_out = 0;
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_DATA;
uvc_event->data.length = req->actual;
memcpy(&uvc_event->data.data, req->buf, req->actual);
v4l2_event_queue(uvc->vdev, &v4l2_event);
}
}
static int
uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
{
struct uvc_device *uvc = to_uvc(f);
struct v4l2_event v4l2_event;
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
/* printk(KERN_INFO "setup request %02x %02x value %04x index %04x %04x\n",
* ctrl->bRequestType, ctrl->bRequest, le16_to_cpu(ctrl->wValue),
* le16_to_cpu(ctrl->wIndex), le16_to_cpu(ctrl->wLength));
*/
if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) {
INFO(f->config->cdev, "invalid request type\n");
return -EINVAL;
}
/* Stall too big requests. */
if (le16_to_cpu(ctrl->wLength) > UVC_MAX_REQUEST_SIZE)
return -EINVAL;
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_SETUP;
memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req));
v4l2_event_queue(uvc->vdev, &v4l2_event);
return 0;
}
static int
uvc_function_get_alt(struct usb_function *f, unsigned interface)
{
struct uvc_device *uvc = to_uvc(f);
INFO(f->config->cdev, "uvc_function_get_alt(%u)\n", interface);
if (interface == uvc->control_intf)
return 0;
else if (interface != uvc->streaming_intf)
return -EINVAL;
else
return uvc->state == UVC_STATE_STREAMING ? 1 : 0;
}
static int
uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
{
struct uvc_device *uvc = to_uvc(f);
struct v4l2_event v4l2_event;
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
if (interface == uvc->control_intf) {
if (alt)
return -EINVAL;
if (uvc->state == UVC_STATE_DISCONNECTED) {
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_CONNECT;
uvc_event->speed = f->config->cdev->gadget->speed;
v4l2_event_queue(uvc->vdev, &v4l2_event);
uvc->state = UVC_STATE_CONNECTED;
}
return 0;
}
if (interface != uvc->streaming_intf)
return -EINVAL;
/* TODO
if (usb_endpoint_xfer_bulk(&uvc->desc.vs_ep))
return alt ? -EINVAL : 0;
*/
switch (alt) {
case 0:
if (uvc->state != UVC_STATE_STREAMING)
return 0;
if (uvc->video.ep)
usb_ep_disable(uvc->video.ep);
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_STREAMOFF;
v4l2_event_queue(uvc->vdev, &v4l2_event);
uvc->state = UVC_STATE_CONNECTED;
break;
case 1:
if (uvc->state != UVC_STATE_CONNECTED)
return 0;
if (uvc->video.ep)
usb_ep_enable(uvc->video.ep, &uvc_streaming_ep);
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_STREAMON;
v4l2_event_queue(uvc->vdev, &v4l2_event);
uvc->state = UVC_STATE_STREAMING;
break;
default:
return -EINVAL;
}
return 0;
}
static void
uvc_function_disable(struct usb_function *f)
{
struct uvc_device *uvc = to_uvc(f);
struct v4l2_event v4l2_event;
INFO(f->config->cdev, "uvc_function_disable\n");
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_DISCONNECT;
v4l2_event_queue(uvc->vdev, &v4l2_event);
uvc->state = UVC_STATE_DISCONNECTED;
}
/* --------------------------------------------------------------------------
* Connection / disconnection
*/
void
uvc_function_connect(struct uvc_device *uvc)
{
struct usb_composite_dev *cdev = uvc->func.config->cdev;
int ret;
if ((ret = usb_function_activate(&uvc->func)) < 0)
INFO(cdev, "UVC connect failed with %d\n", ret);
}
void
uvc_function_disconnect(struct uvc_device *uvc)
{
struct usb_composite_dev *cdev = uvc->func.config->cdev;
int ret;
if ((ret = usb_function_deactivate(&uvc->func)) < 0)
INFO(cdev, "UVC disconnect failed with %d\n", ret);
}
/* --------------------------------------------------------------------------
* USB probe and disconnect
*/
static int
uvc_register_video(struct uvc_device *uvc)
{
struct usb_composite_dev *cdev = uvc->func.config->cdev;
struct video_device *video;
/* TODO reference counting. */
video = video_device_alloc();
if (video == NULL)
return -ENOMEM;
video->parent = &cdev->gadget->dev;
video->minor = -1;
video->fops = &uvc_v4l2_fops;
video->release = video_device_release;
strncpy(video->name, cdev->gadget->name, sizeof(video->name));
uvc->vdev = video;
video_set_drvdata(video, uvc);
return video_register_device(video, VFL_TYPE_GRABBER, -1);
}
#define UVC_COPY_DESCRIPTOR(mem, dst, desc) \
do { \
memcpy(mem, desc, (desc)->bLength); \
*(dst)++ = mem; \
mem += (desc)->bLength; \
} while (0);
#define UVC_COPY_DESCRIPTORS(mem, dst, src) \
do { \
const struct usb_descriptor_header * const *__src; \
for (__src = src; *__src; ++__src) { \
memcpy(mem, *__src, (*__src)->bLength); \
*dst++ = mem; \
mem += (*__src)->bLength; \
} \
} while (0)
static struct usb_descriptor_header ** __init
uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
{
struct uvc_input_header_descriptor *uvc_streaming_header;
struct uvc_header_descriptor *uvc_control_header;
const struct uvc_descriptor_header * const *uvc_streaming_cls;
const struct usb_descriptor_header * const *uvc_streaming_std;
const struct usb_descriptor_header * const *src;
struct usb_descriptor_header **dst;
struct usb_descriptor_header **hdr;
unsigned int control_size;
unsigned int streaming_size;
unsigned int n_desc;
unsigned int bytes;
void *mem;
uvc_streaming_cls = (speed == USB_SPEED_FULL)
? uvc->desc.fs_streaming : uvc->desc.hs_streaming;
uvc_streaming_std = (speed == USB_SPEED_FULL)
? uvc_fs_streaming : uvc_hs_streaming;
/* Descriptors layout
*
* uvc_iad
* uvc_control_intf
* Class-specific UVC control descriptors
* uvc_control_ep
* uvc_control_cs_ep
* uvc_streaming_intf_alt0
* Class-specific UVC streaming descriptors
* uvc_{fs|hs}_streaming
*/
/* Count descriptors and compute their size. */
control_size = 0;
streaming_size = 0;
bytes = uvc_iad.bLength + uvc_control_intf.bLength
+ uvc_control_ep.bLength + uvc_control_cs_ep.bLength
+ uvc_streaming_intf_alt0.bLength;
n_desc = 5;
for (src = (const struct usb_descriptor_header**)uvc->desc.control; *src; ++src) {
control_size += (*src)->bLength;
bytes += (*src)->bLength;
n_desc++;
}
for (src = (const struct usb_descriptor_header**)uvc_streaming_cls; *src; ++src) {
streaming_size += (*src)->bLength;
bytes += (*src)->bLength;
n_desc++;
}
for (src = uvc_streaming_std; *src; ++src) {
bytes += (*src)->bLength;
n_desc++;
}
mem = kmalloc((n_desc + 1) * sizeof(*src) + bytes, GFP_KERNEL);
if (mem == NULL)
return NULL;
hdr = mem;
dst = mem;
mem += (n_desc + 1) * sizeof(*src);
/* Copy the descriptors. */
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_iad);
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_intf);
uvc_control_header = mem;
UVC_COPY_DESCRIPTORS(mem, dst,
(const struct usb_descriptor_header**)uvc->desc.control);
uvc_control_header->wTotalLength = cpu_to_le16(control_size);
uvc_control_header->bInCollection = 1;
uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep);
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_cs_ep);
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_streaming_intf_alt0);
uvc_streaming_header = mem;
UVC_COPY_DESCRIPTORS(mem, dst,
(const struct usb_descriptor_header**)uvc_streaming_cls);
uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size);
uvc_streaming_header->bEndpointAddress = uvc_streaming_ep.bEndpointAddress;
UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std);
*dst = NULL;
return hdr;
}
static void
uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct uvc_device *uvc = to_uvc(f);
INFO(cdev, "uvc_function_unbind\n");
if (uvc->vdev) {
if (uvc->vdev->minor == -1)
video_device_release(uvc->vdev);
else
video_unregister_device(uvc->vdev);
uvc->vdev = NULL;
}
if (uvc->control_ep)
uvc->control_ep->driver_data = NULL;
if (uvc->video.ep)
uvc->video.ep->driver_data = NULL;
if (uvc->control_req) {
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
kfree(uvc->control_buf);
}
kfree(f->descriptors);
kfree(f->hs_descriptors);
kfree(uvc);
}
static int __init
uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct uvc_device *uvc = to_uvc(f);
struct usb_ep *ep;
int ret = -EINVAL;
INFO(cdev, "uvc_function_bind\n");
/* Allocate endpoints. */
ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);
if (!ep) {
INFO(cdev, "Unable to allocate control EP\n");
goto error;
}
uvc->control_ep = ep;
ep->driver_data = uvc;
ep = usb_ep_autoconfig(cdev->gadget, &uvc_streaming_ep);
if (!ep) {
INFO(cdev, "Unable to allocate streaming EP\n");
goto error;
}
uvc->video.ep = ep;
ep->driver_data = uvc;
/* Allocate interface IDs. */
if ((ret = usb_interface_id(c, f)) < 0)
goto error;
uvc_iad.bFirstInterface = ret;
uvc_control_intf.bInterfaceNumber = ret;
uvc->control_intf = ret;
if ((ret = usb_interface_id(c, f)) < 0)
goto error;
uvc_streaming_intf_alt0.bInterfaceNumber = ret;
uvc_streaming_intf_alt1.bInterfaceNumber = ret;
uvc->streaming_intf = ret;
/* Copy descriptors. */
f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
/* Preallocate control endpoint request. */
uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL);
if (uvc->control_req == NULL || uvc->control_buf == NULL) {
ret = -ENOMEM;
goto error;
}
uvc->control_req->buf = uvc->control_buf;
uvc->control_req->complete = uvc_function_ep0_complete;
uvc->control_req->context = uvc;
/* Avoid letting this gadget enumerate until the userspace server is
* active.
*/
if ((ret = usb_function_deactivate(f)) < 0)
goto error;
/* Initialise video. */
ret = uvc_video_init(&uvc->video);
if (ret < 0)
goto error;
/* Register a V4L2 device. */
ret = uvc_register_video(uvc);
if (ret < 0) {
printk(KERN_INFO "Unable to register video device\n");
goto error;
}
return 0;
error:
uvc_function_unbind(c, f);
return ret;
}
/* --------------------------------------------------------------------------
* USB gadget function
*/
/**
* uvc_bind_config - add a UVC function to a configuration
* @c: the configuration to support the UVC instance
* Context: single threaded during gadget setup
*
* Returns zero on success, else negative errno.
*
* Caller must have called @uvc_setup(). Caller is also responsible for
* calling @uvc_cleanup() before module unload.
*/
int __init
uvc_bind_config(struct usb_configuration *c,
const struct uvc_descriptor_header * const *control,
const struct uvc_descriptor_header * const *fs_streaming,
const struct uvc_descriptor_header * const *hs_streaming)
{
struct uvc_device *uvc;
int ret = 0;
/* TODO Check if the USB device controller supports the required
* features.
*/
if (!gadget_is_dualspeed(c->cdev->gadget))
return -EINVAL;
uvc = kzalloc(sizeof(*uvc), GFP_KERNEL);
if (uvc == NULL)
return -ENOMEM;
uvc->state = UVC_STATE_DISCONNECTED;
/* Validate the descriptors. */
if (control == NULL || control[0] == NULL ||
control[0]->bDescriptorSubType != UVC_DT_HEADER)
goto error;
if (fs_streaming == NULL || fs_streaming[0] == NULL ||
fs_streaming[0]->bDescriptorSubType != UVC_DT_INPUT_HEADER)
goto error;
if (hs_streaming == NULL || hs_streaming[0] == NULL ||
hs_streaming[0]->bDescriptorSubType != UVC_DT_INPUT_HEADER)
goto error;
uvc->desc.control = control;
uvc->desc.fs_streaming = fs_streaming;
uvc->desc.hs_streaming = hs_streaming;
/* Allocate string descriptor numbers. */
if ((ret = usb_string_id(c->cdev)) < 0)
goto error;
uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret;
uvc_iad.iFunction = ret;
if ((ret = usb_string_id(c->cdev)) < 0)
goto error;
uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret;
uvc_control_intf.iInterface = ret;
if ((ret = usb_string_id(c->cdev)) < 0)
goto error;
uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret;
uvc_streaming_intf_alt0.iInterface = ret;
uvc_streaming_intf_alt1.iInterface = ret;
/* Register the function. */
uvc->func.name = "uvc";
uvc->func.strings = uvc_function_strings;
uvc->func.bind = uvc_function_bind;
uvc->func.unbind = uvc_function_unbind;
uvc->func.get_alt = uvc_function_get_alt;
uvc->func.set_alt = uvc_function_set_alt;
uvc->func.disable = uvc_function_disable;
uvc->func.setup = uvc_function_setup;
ret = usb_add_function(c, &uvc->func);
if (ret)
kfree(uvc);
return 0;
error:
kfree(uvc);
return ret;
}
module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(trace, "Trace level bitmask");

View File

@ -0,0 +1,376 @@
/*
* f_uvc.h -- USB Video Class Gadget driver
*
* Copyright (C) 2009-2010
* Laurent Pinchart (laurent.pinchart@ideasonboard.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.
*
*/
#ifndef _F_UVC_H_
#define _F_UVC_H_
#include <linux/usb/composite.h>
#define USB_CLASS_VIDEO_CONTROL 1
#define USB_CLASS_VIDEO_STREAMING 2
struct uvc_descriptor_header {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
} __attribute__ ((packed));
struct uvc_header_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u16 bcdUVC;
__u16 wTotalLength;
__u32 dwClockFrequency;
__u8 bInCollection;
__u8 baInterfaceNr[];
} __attribute__((__packed__));
#define UVC_HEADER_DESCRIPTOR(n) uvc_header_descriptor_##n
#define DECLARE_UVC_HEADER_DESCRIPTOR(n) \
struct UVC_HEADER_DESCRIPTOR(n) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u16 bcdUVC; \
__u16 wTotalLength; \
__u32 dwClockFrequency; \
__u8 bInCollection; \
__u8 baInterfaceNr[n]; \
} __attribute__ ((packed))
struct uvc_input_terminal_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bTerminalID;
__u16 wTerminalType;
__u8 bAssocTerminal;
__u8 iTerminal;
} __attribute__((__packed__));
struct uvc_output_terminal_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bTerminalID;
__u16 wTerminalType;
__u8 bAssocTerminal;
__u8 bSourceID;
__u8 iTerminal;
} __attribute__((__packed__));
struct uvc_camera_terminal_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bTerminalID;
__u16 wTerminalType;
__u8 bAssocTerminal;
__u8 iTerminal;
__u16 wObjectiveFocalLengthMin;
__u16 wObjectiveFocalLengthMax;
__u16 wOcularFocalLength;
__u8 bControlSize;
__u8 bmControls[3];
} __attribute__((__packed__));
struct uvc_selector_unit_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bUnitID;
__u8 bNrInPins;
__u8 baSourceID[0];
__u8 iSelector;
} __attribute__((__packed__));
#define UVC_SELECTOR_UNIT_DESCRIPTOR(n) \
uvc_selector_unit_descriptor_##n
#define DECLARE_UVC_SELECTOR_UNIT_DESCRIPTOR(n) \
struct UVC_SELECTOR_UNIT_DESCRIPTOR(n) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u8 bUnitID; \
__u8 bNrInPins; \
__u8 baSourceID[n]; \
__u8 iSelector; \
} __attribute__ ((packed))
struct uvc_processing_unit_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bUnitID;
__u8 bSourceID;
__u16 wMaxMultiplier;
__u8 bControlSize;
__u8 bmControls[2];
__u8 iProcessing;
} __attribute__((__packed__));
struct uvc_extension_unit_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bUnitID;
__u8 guidExtensionCode[16];
__u8 bNumControls;
__u8 bNrInPins;
__u8 baSourceID[0];
__u8 bControlSize;
__u8 bmControls[0];
__u8 iExtension;
} __attribute__((__packed__));
#define UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) \
uvc_extension_unit_descriptor_##p_##n
#define DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) \
struct UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u8 bUnitID; \
__u8 guidExtensionCode[16]; \
__u8 bNumControls; \
__u8 bNrInPins; \
__u8 baSourceID[p]; \
__u8 bControlSize; \
__u8 bmControls[n]; \
__u8 iExtension; \
} __attribute__ ((packed))
struct uvc_control_endpoint_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u16 wMaxTransferSize;
} __attribute__((__packed__));
#define UVC_DT_HEADER 1
#define UVC_DT_INPUT_TERMINAL 2
#define UVC_DT_OUTPUT_TERMINAL 3
#define UVC_DT_SELECTOR_UNIT 4
#define UVC_DT_PROCESSING_UNIT 5
#define UVC_DT_EXTENSION_UNIT 6
#define UVC_DT_HEADER_SIZE(n) (12+(n))
#define UVC_DT_INPUT_TERMINAL_SIZE 8
#define UVC_DT_OUTPUT_TERMINAL_SIZE 9
#define UVC_DT_CAMERA_TERMINAL_SIZE(n) (15+(n))
#define UVC_DT_SELECTOR_UNIT_SIZE(n) (6+(n))
#define UVC_DT_PROCESSING_UNIT_SIZE(n) (9+(n))
#define UVC_DT_EXTENSION_UNIT_SIZE(p,n) (24+(p)+(n))
#define UVC_DT_CONTROL_ENDPOINT_SIZE 5
struct uvc_input_header_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bNumFormats;
__u16 wTotalLength;
__u8 bEndpointAddress;
__u8 bmInfo;
__u8 bTerminalLink;
__u8 bStillCaptureMethod;
__u8 bTriggerSupport;
__u8 bTriggerUsage;
__u8 bControlSize;
__u8 bmaControls[];
} __attribute__((__packed__));
#define UVC_INPUT_HEADER_DESCRIPTOR(n, p) \
uvc_input_header_descriptor_##n_##p
#define DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(n, p) \
struct UVC_INPUT_HEADER_DESCRIPTOR(n, p) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u8 bNumFormats; \
__u16 wTotalLength; \
__u8 bEndpointAddress; \
__u8 bmInfo; \
__u8 bTerminalLink; \
__u8 bStillCaptureMethod; \
__u8 bTriggerSupport; \
__u8 bTriggerUsage; \
__u8 bControlSize; \
__u8 bmaControls[p][n]; \
} __attribute__ ((packed))
struct uvc_output_header_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bNumFormats;
__u16 wTotalLength;
__u8 bEndpointAddress;
__u8 bTerminalLink;
__u8 bControlSize;
__u8 bmaControls[];
} __attribute__((__packed__));
#define UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \
uvc_output_header_descriptor_##n_##p
#define DECLARE_UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \
struct UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u8 bNumFormats; \
__u16 wTotalLength; \
__u8 bEndpointAddress; \
__u8 bTerminalLink; \
__u8 bControlSize; \
__u8 bmaControls[p][n]; \
} __attribute__ ((packed))
struct uvc_format_uncompressed {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bFormatIndex;
__u8 bNumFrameDescriptors;
__u8 guidFormat[16];
__u8 bBitsPerPixel;
__u8 bDefaultFrameIndex;
__u8 bAspectRatioX;
__u8 bAspectRatioY;
__u8 bmInterfaceFlags;
__u8 bCopyProtect;
} __attribute__((__packed__));
struct uvc_frame_uncompressed {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bFrameIndex;
__u8 bmCapabilities;
__u16 wWidth;
__u16 wHeight;
__u32 dwMinBitRate;
__u32 dwMaxBitRate;
__u32 dwMaxVideoFrameBufferSize;
__u32 dwDefaultFrameInterval;
__u8 bFrameIntervalType;
__u32 dwFrameInterval[];
} __attribute__((__packed__));
#define UVC_FRAME_UNCOMPRESSED(n) \
uvc_frame_uncompressed_##n
#define DECLARE_UVC_FRAME_UNCOMPRESSED(n) \
struct UVC_FRAME_UNCOMPRESSED(n) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u8 bFrameIndex; \
__u8 bmCapabilities; \
__u16 wWidth; \
__u16 wHeight; \
__u32 dwMinBitRate; \
__u32 dwMaxBitRate; \
__u32 dwMaxVideoFrameBufferSize; \
__u32 dwDefaultFrameInterval; \
__u8 bFrameIntervalType; \
__u32 dwFrameInterval[n]; \
} __attribute__ ((packed))
struct uvc_format_mjpeg {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bFormatIndex;
__u8 bNumFrameDescriptors;
__u8 bmFlags;
__u8 bDefaultFrameIndex;
__u8 bAspectRatioX;
__u8 bAspectRatioY;
__u8 bmInterfaceFlags;
__u8 bCopyProtect;
} __attribute__((__packed__));
struct uvc_frame_mjpeg {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bFrameIndex;
__u8 bmCapabilities;
__u16 wWidth;
__u16 wHeight;
__u32 dwMinBitRate;
__u32 dwMaxBitRate;
__u32 dwMaxVideoFrameBufferSize;
__u32 dwDefaultFrameInterval;
__u8 bFrameIntervalType;
__u32 dwFrameInterval[];
} __attribute__((__packed__));
#define UVC_FRAME_MJPEG(n) \
uvc_frame_mjpeg_##n
#define DECLARE_UVC_FRAME_MJPEG(n) \
struct UVC_FRAME_MJPEG(n) { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubType; \
__u8 bFrameIndex; \
__u8 bmCapabilities; \
__u16 wWidth; \
__u16 wHeight; \
__u32 dwMinBitRate; \
__u32 dwMaxBitRate; \
__u32 dwMaxVideoFrameBufferSize; \
__u32 dwDefaultFrameInterval; \
__u8 bFrameIntervalType; \
__u32 dwFrameInterval[n]; \
} __attribute__ ((packed))
struct uvc_color_matching_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bColorPrimaries;
__u8 bTransferCharacteristics;
__u8 bMatrixCoefficients;
} __attribute__((__packed__));
#define UVC_DT_INPUT_HEADER 1
#define UVC_DT_OUTPUT_HEADER 2
#define UVC_DT_FORMAT_UNCOMPRESSED 4
#define UVC_DT_FRAME_UNCOMPRESSED 5
#define UVC_DT_FORMAT_MJPEG 6
#define UVC_DT_FRAME_MJPEG 7
#define UVC_DT_COLOR_MATCHING 13
#define UVC_DT_INPUT_HEADER_SIZE(n, p) (13+(n*p))
#define UVC_DT_OUTPUT_HEADER_SIZE(n, p) (9+(n*p))
#define UVC_DT_FORMAT_UNCOMPRESSED_SIZE 27
#define UVC_DT_FRAME_UNCOMPRESSED_SIZE(n) (26+4*(n))
#define UVC_DT_FORMAT_MJPEG_SIZE 11
#define UVC_DT_FRAME_MJPEG_SIZE(n) (26+4*(n))
#define UVC_DT_COLOR_MATCHING_SIZE 6
extern int uvc_bind_config(struct usb_configuration *c,
const struct uvc_descriptor_header * const *control,
const struct uvc_descriptor_header * const *fs_streaming,
const struct uvc_descriptor_header * const *hs_streaming);
#endif /* _F_UVC_H_ */

View File

@ -50,12 +50,14 @@ int fsl_udc_clk_init(struct platform_device *pdev)
goto egusb;
}
freq = clk_get_rate(mxc_usb_clk);
if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
(freq < 59999000 || freq > 60001000)) {
dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq);
ret = -EINVAL;
goto eclkrate;
if (!cpu_is_mx51()) {
freq = clk_get_rate(mxc_usb_clk);
if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
(freq < 59999000 || freq > 60001000)) {
dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq);
ret = -EINVAL;
goto eclkrate;
}
}
ret = clk_enable(mxc_usb_clk);

View File

@ -489,7 +489,7 @@ static int fsl_ep_enable(struct usb_ep *_ep,
case USB_ENDPOINT_XFER_ISOC:
/* Calculate transactions needed for high bandwidth iso */
mult = (unsigned char)(1 + ((max >> 11) & 0x03));
max = max & 0x8ff; /* bit 0~10 */
max = max & 0x7ff; /* bit 0~10 */
/* 3 transactions at most */
if (mult > 3)
goto en_done;

View File

@ -0,0 +1,426 @@
#include <linux/module.h>
#include <linux/utsname.h>
/*
* kbuild is not very cooperative with respect to linking separately
* compiled library objects into one module. So for now we won't use
* separate compilation ... ensuring init/exit sections work to shrink
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#include "composite.c"
#include "usbstring.c"
#include "config.c"
#include "epautoconf.c"
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
# if defined USB_ETH_RNDIS
# undef USB_ETH_RNDIS
# endif
# ifdef CONFIG_USB_FUNCTIONFS_RNDIS
# define USB_ETH_RNDIS y
# endif
# include "f_ecm.c"
# include "f_subset.c"
# ifdef USB_ETH_RNDIS
# include "f_rndis.c"
# include "rndis.c"
# endif
# include "u_ether.c"
static u8 gfs_hostaddr[ETH_ALEN];
#else
# if !defined CONFIG_USB_FUNCTIONFS_GENERIC
# define CONFIG_USB_FUNCTIONFS_GENERIC
# endif
# define gether_cleanup() do { } while (0)
# define gether_setup(gadget, hostaddr) ((int)0)
#endif
#include "f_fs.c"
#define DRIVER_NAME "g_ffs"
#define DRIVER_DESC "USB Function Filesystem"
#define DRIVER_VERSION "24 Aug 2004"
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Michal Nazarewicz");
MODULE_LICENSE("GPL");
static unsigned short gfs_vendor_id = 0x0525; /* XXX NetChip */
static unsigned short gfs_product_id = 0xa4ac; /* XXX */
static struct usb_device_descriptor gfs_dev_desc = {
.bLength = sizeof gfs_dev_desc,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PER_INTERFACE,
/* Vendor and product id can be overridden by module parameters. */
/* .idVendor = cpu_to_le16(gfs_vendor_id), */
/* .idProduct = cpu_to_le16(gfs_product_id), */
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
/* NO SERIAL NUMBER */
.bNumConfigurations = 1,
};
#define GFS_MODULE_PARAM_DESC(name, field) \
MODULE_PARM_DESC(name, "Value of the " #field " field of the device descriptor sent to the host. Takes effect only prior to the user-space driver registering to the FunctionFS.")
module_param_named(usb_class, gfs_dev_desc.bDeviceClass, byte, 0644);
GFS_MODULE_PARAM_DESC(usb_class, bDeviceClass);
module_param_named(usb_subclass, gfs_dev_desc.bDeviceSubClass, byte, 0644);
GFS_MODULE_PARAM_DESC(usb_subclass, bDeviceSubClass);
module_param_named(usb_protocol, gfs_dev_desc.bDeviceProtocol, byte, 0644);
GFS_MODULE_PARAM_DESC(usb_protocol, bDeviceProtocol);
module_param_named(usb_vendor, gfs_vendor_id, ushort, 0644);
GFS_MODULE_PARAM_DESC(usb_vendor, idVendor);
module_param_named(usb_product, gfs_product_id, ushort, 0644);
GFS_MODULE_PARAM_DESC(usb_product, idProduct);
static const struct usb_descriptor_header *gfs_otg_desc[] = {
(const struct usb_descriptor_header *)
&(const struct usb_otg_descriptor) {
.bLength = sizeof(struct usb_otg_descriptor),
.bDescriptorType = USB_DT_OTG,
/* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ... */
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
},
NULL
};
/* string IDs are assigned dynamically */
enum {
GFS_STRING_MANUFACTURER_IDX,
GFS_STRING_PRODUCT_IDX,
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
GFS_STRING_RNDIS_CONFIG_IDX,
#endif
#ifdef CONFIG_USB_FUNCTIONFS_ETH
GFS_STRING_ECM_CONFIG_IDX,
#endif
#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
GFS_STRING_GENERIC_CONFIG_IDX,
#endif
};
static char gfs_manufacturer[50];
static const char gfs_driver_desc[] = DRIVER_DESC;
static const char gfs_short_name[] = DRIVER_NAME;
static struct usb_string gfs_strings[] = {
[GFS_STRING_MANUFACTURER_IDX].s = gfs_manufacturer,
[GFS_STRING_PRODUCT_IDX].s = gfs_driver_desc,
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
[GFS_STRING_RNDIS_CONFIG_IDX].s = "FunctionFS + RNDIS",
#endif
#ifdef CONFIG_USB_FUNCTIONFS_ETH
[GFS_STRING_ECM_CONFIG_IDX].s = "FunctionFS + ECM",
#endif
#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
[GFS_STRING_GENERIC_CONFIG_IDX].s = "FunctionFS",
#endif
{ } /* end of list */
};
static struct usb_gadget_strings *gfs_dev_strings[] = {
&(struct usb_gadget_strings) {
.language = 0x0409, /* en-us */
.strings = gfs_strings,
},
NULL,
};
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
static int gfs_do_rndis_config(struct usb_configuration *c);
static struct usb_configuration gfs_rndis_config_driver = {
.label = "FunctionFS + RNDIS",
.bind = gfs_do_rndis_config,
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
# define gfs_add_rndis_config(cdev) \
usb_add_config(cdev, &gfs_rndis_config_driver)
#else
# define gfs_add_rndis_config(cdev) 0
#endif
#ifdef CONFIG_USB_FUNCTIONFS_ETH
static int gfs_do_ecm_config(struct usb_configuration *c);
static struct usb_configuration gfs_ecm_config_driver = {
.label = "FunctionFS + ECM",
.bind = gfs_do_ecm_config,
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
# define gfs_add_ecm_config(cdev) \
usb_add_config(cdev, &gfs_ecm_config_driver)
#else
# define gfs_add_ecm_config(cdev) 0
#endif
#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
static int gfs_do_generic_config(struct usb_configuration *c);
static struct usb_configuration gfs_generic_config_driver = {
.label = "FunctionFS",
.bind = gfs_do_generic_config,
.bConfigurationValue = 2,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
# define gfs_add_generic_config(cdev) \
usb_add_config(cdev, &gfs_generic_config_driver)
#else
# define gfs_add_generic_config(cdev) 0
#endif
static int gfs_bind(struct usb_composite_dev *cdev);
static int gfs_unbind(struct usb_composite_dev *cdev);
static struct usb_composite_driver gfs_driver = {
.name = gfs_short_name,
.dev = &gfs_dev_desc,
.strings = gfs_dev_strings,
.bind = gfs_bind,
.unbind = gfs_unbind,
};
static struct ffs_data *gfs_ffs_data;
static unsigned long gfs_registered;
static int gfs_init(void)
{
ENTER();
return functionfs_init();
}
module_init(gfs_init);
static void gfs_exit(void)
{
ENTER();
if (test_and_clear_bit(0, &gfs_registered))
usb_composite_unregister(&gfs_driver);
functionfs_cleanup();
}
module_exit(gfs_exit);
static int functionfs_ready_callback(struct ffs_data *ffs)
{
int ret;
ENTER();
if (WARN_ON(test_and_set_bit(0, &gfs_registered)))
return -EBUSY;
gfs_ffs_data = ffs;
ret = usb_composite_register(&gfs_driver);
if (unlikely(ret < 0))
clear_bit(0, &gfs_registered);
return ret;
}
static void functionfs_closed_callback(struct ffs_data *ffs)
{
ENTER();
if (test_and_clear_bit(0, &gfs_registered))
usb_composite_unregister(&gfs_driver);
}
static int functionfs_check_dev_callback(const char *dev_name)
{
return 0;
}
static int gfs_bind(struct usb_composite_dev *cdev)
{
int ret;
ENTER();
if (WARN_ON(!gfs_ffs_data))
return -ENODEV;
ret = gether_setup(cdev->gadget, gfs_hostaddr);
if (unlikely(ret < 0))
goto error_quick;
gfs_dev_desc.idVendor = cpu_to_le16(gfs_vendor_id);
gfs_dev_desc.idProduct = cpu_to_le16(gfs_product_id);
snprintf(gfs_manufacturer, sizeof gfs_manufacturer, "%s %s with %s",
init_utsname()->sysname, init_utsname()->release,
cdev->gadget->name);
ret = usb_string_id(cdev);
if (unlikely(ret < 0))
goto error;
gfs_strings[GFS_STRING_MANUFACTURER_IDX].id = ret;
gfs_dev_desc.iManufacturer = ret;
ret = usb_string_id(cdev);
if (unlikely(ret < 0))
goto error;
gfs_strings[GFS_STRING_PRODUCT_IDX].id = ret;
gfs_dev_desc.iProduct = ret;
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
ret = usb_string_id(cdev);
if (unlikely(ret < 0))
goto error;
gfs_strings[GFS_STRING_RNDIS_CONFIG_IDX].id = ret;
gfs_rndis_config_driver.iConfiguration = ret;
#endif
#ifdef CONFIG_USB_FUNCTIONFS_ETH
ret = usb_string_id(cdev);
if (unlikely(ret < 0))
goto error;
gfs_strings[GFS_STRING_ECM_CONFIG_IDX].id = ret;
gfs_ecm_config_driver.iConfiguration = ret;
#endif
#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
ret = usb_string_id(cdev);
if (unlikely(ret < 0))
goto error;
gfs_strings[GFS_STRING_GENERIC_CONFIG_IDX].id = ret;
gfs_generic_config_driver.iConfiguration = ret;
#endif
ret = functionfs_bind(gfs_ffs_data, cdev);
if (unlikely(ret < 0))
goto error;
ret = gfs_add_rndis_config(cdev);
if (unlikely(ret < 0))
goto error_unbind;
ret = gfs_add_ecm_config(cdev);
if (unlikely(ret < 0))
goto error_unbind;
ret = gfs_add_generic_config(cdev);
if (unlikely(ret < 0))
goto error_unbind;
return 0;
error_unbind:
functionfs_unbind(gfs_ffs_data);
error:
gether_cleanup();
error_quick:
gfs_ffs_data = NULL;
return ret;
}
static int gfs_unbind(struct usb_composite_dev *cdev)
{
ENTER();
/* We may have been called in an error recovery frem
* composite_bind() after gfs_unbind() failure so we need to
* check if gfs_ffs_data is not NULL since gfs_bind() handles
* all error recovery itself. I'd rather we werent called
* from composite on orror recovery, but what you're gonna
* do...? */
if (gfs_ffs_data) {
gether_cleanup();
functionfs_unbind(gfs_ffs_data);
gfs_ffs_data = NULL;
}
return 0;
}
static int __gfs_do_config(struct usb_configuration *c,
int (*eth)(struct usb_configuration *c, u8 *ethaddr),
u8 *ethaddr)
{
int ret;
if (WARN_ON(!gfs_ffs_data))
return -ENODEV;
if (gadget_is_otg(c->cdev->gadget)) {
c->descriptors = gfs_otg_desc;
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
if (eth) {
ret = eth(c, ethaddr);
if (unlikely(ret < 0))
return ret;
}
ret = functionfs_add(c->cdev, c, gfs_ffs_data);
if (unlikely(ret < 0))
return ret;
return 0;
}
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
static int gfs_do_rndis_config(struct usb_configuration *c)
{
ENTER();
return __gfs_do_config(c, rndis_bind_config, gfs_hostaddr);
}
#endif
#ifdef CONFIG_USB_FUNCTIONFS_ETH
static int gfs_do_ecm_config(struct usb_configuration *c)
{
ENTER();
return __gfs_do_config(c,
can_support_ecm(c->cdev->gadget)
? ecm_bind_config : geth_bind_config,
gfs_hostaddr);
}
#endif
#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
static int gfs_do_generic_config(struct usb_configuration *c)
{
ENTER();
return __gfs_do_config(c, NULL, NULL);
}
#endif

View File

@ -0,0 +1,298 @@
/*
* hid.c -- HID Composite driver
*
* Based on multi.c
*
* Copyright (C) 2010 Fabien Chouteau <fabien.chouteau@barco.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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/list.h>
#define DRIVER_DESC "HID Gadget"
#define DRIVER_VERSION "2010/03/16"
/*-------------------------------------------------------------------------*/
#define HIDG_VENDOR_NUM 0x0525 /* XXX NetChip */
#define HIDG_PRODUCT_NUM 0xa4ac /* Linux-USB HID gadget */
/*-------------------------------------------------------------------------*/
/*
* kbuild is not very cooperative with respect to linking separately
* compiled library objects into one module. So for now we won't use
* separate compilation ... ensuring init/exit sections work to shrink
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#include "composite.c"
#include "usbstring.c"
#include "config.c"
#include "epautoconf.c"
#include "f_hid.c"
struct hidg_func_node {
struct list_head node;
struct hidg_func_descriptor *func;
};
static LIST_HEAD(hidg_func_list);
/*-------------------------------------------------------------------------*/
static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = cpu_to_le16(0x0200),
/* .bDeviceClass = USB_CLASS_COMM, */
/* .bDeviceSubClass = 0, */
/* .bDeviceProtocol = 0, */
.bDeviceClass = 0xEF,
.bDeviceSubClass = 2,
.bDeviceProtocol = 1,
/* .bMaxPacketSize0 = f(hardware) */
/* Vendor and product id can be overridden by module parameters. */
.idVendor = cpu_to_le16(HIDG_VENDOR_NUM),
.idProduct = cpu_to_le16(HIDG_PRODUCT_NUM),
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
/* NO SERIAL NUMBER */
.bNumConfigurations = 1,
};
static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
/* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
NULL,
};
/* string IDs are assigned dynamically */
#define STRING_MANUFACTURER_IDX 0
#define STRING_PRODUCT_IDX 1
static char manufacturer[50];
static struct usb_string strings_dev[] = {
[STRING_MANUFACTURER_IDX].s = manufacturer,
[STRING_PRODUCT_IDX].s = DRIVER_DESC,
{ } /* end of list */
};
static struct usb_gadget_strings stringtab_dev = {
.language = 0x0409, /* en-us */
.strings = strings_dev,
};
static struct usb_gadget_strings *dev_strings[] = {
&stringtab_dev,
NULL,
};
/****************************** Configurations ******************************/
static int __init do_config(struct usb_configuration *c)
{
struct hidg_func_node *e;
int func = 0, status = 0;
if (gadget_is_otg(c->cdev->gadget)) {
c->descriptors = otg_desc;
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
list_for_each_entry(e, &hidg_func_list, node) {
status = hidg_bind_config(c, e->func, func++);
if (status)
break;
}
return status;
}
static struct usb_configuration config_driver = {
.label = "HID Gadget",
.bind = do_config,
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
/****************************** Gadget Bind ******************************/
static int __init hid_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
struct list_head *tmp;
int status, gcnum, funcs = 0;
list_for_each(tmp, &hidg_func_list)
funcs++;
if (!funcs)
return -ENODEV;
/* set up HID */
status = ghid_setup(cdev->gadget, funcs);
if (status < 0)
return status;
gcnum = usb_gadget_controller_number(gadget);
if (gcnum >= 0)
device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
else
device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099);
/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue.
*/
/* device descriptor strings: manufacturer, product */
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
init_utsname()->sysname, init_utsname()->release,
gadget->name);
status = usb_string_id(cdev);
if (status < 0)
return status;
strings_dev[STRING_MANUFACTURER_IDX].id = status;
device_desc.iManufacturer = status;
status = usb_string_id(cdev);
if (status < 0)
return status;
strings_dev[STRING_PRODUCT_IDX].id = status;
device_desc.iProduct = status;
/* register our configuration */
status = usb_add_config(cdev, &config_driver);
if (status < 0)
return status;
dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
return 0;
}
static int __exit hid_unbind(struct usb_composite_dev *cdev)
{
ghid_cleanup();
return 0;
}
static int __init hidg_plat_driver_probe(struct platform_device *pdev)
{
struct hidg_func_descriptor *func = pdev->dev.platform_data;
struct hidg_func_node *entry;
if (!func) {
dev_err(&pdev->dev, "Platform data missing\n");
return -ENODEV;
}
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
entry->func = func;
list_add_tail(&entry->node, &hidg_func_list);
return 0;
}
static int __devexit hidg_plat_driver_remove(struct platform_device *pdev)
{
struct hidg_func_node *e, *n;
list_for_each_entry_safe(e, n, &hidg_func_list, node) {
list_del(&e->node);
kfree(e);
}
return 0;
}
/****************************** Some noise ******************************/
static struct usb_composite_driver hidg_driver = {
.name = "g_hid",
.dev = &device_desc,
.strings = dev_strings,
.bind = hid_bind,
.unbind = __exit_p(hid_unbind),
};
static struct platform_driver hidg_plat_driver = {
.remove = __devexit_p(hidg_plat_driver_remove),
.driver = {
.owner = THIS_MODULE,
.name = "hidg",
},
};
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Fabien Chouteau, Peter Korsgaard");
MODULE_LICENSE("GPL");
static int __init hidg_init(void)
{
int status;
status = platform_driver_probe(&hidg_plat_driver,
hidg_plat_driver_probe);
if (status < 0)
return status;
status = usb_composite_register(&hidg_driver);
if (status < 0)
platform_driver_unregister(&hidg_plat_driver);
return status;
}
module_init(hidg_init);
static void __exit hidg_cleanup(void)
{
platform_driver_unregister(&hidg_plat_driver);
usb_composite_unregister(&hidg_driver);
}
module_exit(hidg_cleanup);

View File

@ -360,7 +360,7 @@ struct pxa_ep {
* Specific pxa endpoint data, needed for hardware initialization
*/
unsigned dir_in:1;
unsigned addr:3;
unsigned addr:4;
unsigned config:2;
unsigned interface:3;
unsigned alternate:3;

View File

@ -715,7 +715,7 @@ static u8 __init nibble(unsigned char c)
return 0;
}
static int __init get_ether_addr(const char *str, u8 *dev_addr)
static int get_ether_addr(const char *str, u8 *dev_addr)
{
if (str) {
unsigned i;
@ -764,7 +764,7 @@ static struct device_type gadget_type = {
*
* Returns negative errno, or zero on success
*/
int __init gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
{
struct eth_dev *dev;
struct net_device *net;

View File

@ -0,0 +1,241 @@
/*
* uvc_gadget.h -- USB Video Class Gadget driver
*
* Copyright (C) 2009-2010
* Laurent Pinchart (laurent.pinchart@ideasonboard.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.
*
*/
#ifndef _UVC_GADGET_H_
#define _UVC_GADGET_H_
#include <linux/ioctl.h>
#include <linux/types.h>
#include <linux/usb/ch9.h>
#define UVC_EVENT_FIRST (V4L2_EVENT_PRIVATE_START + 0)
#define UVC_EVENT_CONNECT (V4L2_EVENT_PRIVATE_START + 0)
#define UVC_EVENT_DISCONNECT (V4L2_EVENT_PRIVATE_START + 1)
#define UVC_EVENT_STREAMON (V4L2_EVENT_PRIVATE_START + 2)
#define UVC_EVENT_STREAMOFF (V4L2_EVENT_PRIVATE_START + 3)
#define UVC_EVENT_SETUP (V4L2_EVENT_PRIVATE_START + 4)
#define UVC_EVENT_DATA (V4L2_EVENT_PRIVATE_START + 5)
#define UVC_EVENT_LAST (V4L2_EVENT_PRIVATE_START + 5)
struct uvc_request_data
{
unsigned int length;
__u8 data[60];
};
struct uvc_event
{
union {
enum usb_device_speed speed;
struct usb_ctrlrequest req;
struct uvc_request_data data;
};
};
#define UVCIOC_SEND_RESPONSE _IOW('U', 1, struct uvc_request_data)
#define UVC_INTF_CONTROL 0
#define UVC_INTF_STREAMING 1
/* ------------------------------------------------------------------------
* UVC constants & structures
*/
/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
#define UVC_STREAM_EOH (1 << 7)
#define UVC_STREAM_ERR (1 << 6)
#define UVC_STREAM_STI (1 << 5)
#define UVC_STREAM_RES (1 << 4)
#define UVC_STREAM_SCR (1 << 3)
#define UVC_STREAM_PTS (1 << 2)
#define UVC_STREAM_EOF (1 << 1)
#define UVC_STREAM_FID (1 << 0)
struct uvc_streaming_control {
__u16 bmHint;
__u8 bFormatIndex;
__u8 bFrameIndex;
__u32 dwFrameInterval;
__u16 wKeyFrameRate;
__u16 wPFrameRate;
__u16 wCompQuality;
__u16 wCompWindowSize;
__u16 wDelay;
__u32 dwMaxVideoFrameSize;
__u32 dwMaxPayloadTransferSize;
__u32 dwClockFrequency;
__u8 bmFramingInfo;
__u8 bPreferedVersion;
__u8 bMinVersion;
__u8 bMaxVersion;
} __attribute__((__packed__));
/* ------------------------------------------------------------------------
* Debugging, printing and logging
*/
#ifdef __KERNEL__
#include <linux/usb.h> /* For usb_endpoint_* */
#include <linux/usb/gadget.h>
#include <linux/videodev2.h>
#include <media/v4l2-fh.h>
#include "uvc_queue.h"
#define UVC_TRACE_PROBE (1 << 0)
#define UVC_TRACE_DESCR (1 << 1)
#define UVC_TRACE_CONTROL (1 << 2)
#define UVC_TRACE_FORMAT (1 << 3)
#define UVC_TRACE_CAPTURE (1 << 4)
#define UVC_TRACE_CALLS (1 << 5)
#define UVC_TRACE_IOCTL (1 << 6)
#define UVC_TRACE_FRAME (1 << 7)
#define UVC_TRACE_SUSPEND (1 << 8)
#define UVC_TRACE_STATUS (1 << 9)
#define UVC_WARN_MINMAX 0
#define UVC_WARN_PROBE_DEF 1
extern unsigned int uvc_trace_param;
#define uvc_trace(flag, msg...) \
do { \
if (uvc_trace_param & flag) \
printk(KERN_DEBUG "uvcvideo: " msg); \
} while (0)
#define uvc_warn_once(dev, warn, msg...) \
do { \
if (!test_and_set_bit(warn, &dev->warnings)) \
printk(KERN_INFO "uvcvideo: " msg); \
} while (0)
#define uvc_printk(level, msg...) \
printk(level "uvcvideo: " msg)
/* ------------------------------------------------------------------------
* Driver specific constants
*/
#define DRIVER_VERSION "0.1.0"
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 0)
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define UVC_NUM_REQUESTS 4
#define UVC_MAX_REQUEST_SIZE 64
#define UVC_MAX_EVENTS 4
#define USB_DT_INTERFACE_ASSOCIATION_SIZE 8
#define USB_CLASS_MISC 0xef
/* ------------------------------------------------------------------------
* Structures
*/
struct uvc_video
{
struct usb_ep *ep;
/* Frame parameters */
u8 bpp;
u32 fcc;
unsigned int width;
unsigned int height;
unsigned int imagesize;
/* Requests */
unsigned int req_size;
struct usb_request *req[UVC_NUM_REQUESTS];
__u8 *req_buffer[UVC_NUM_REQUESTS];
struct list_head req_free;
spinlock_t req_lock;
void (*encode) (struct usb_request *req, struct uvc_video *video,
struct uvc_buffer *buf);
/* Context data used by the completion handler */
__u32 payload_size;
__u32 max_payload_size;
struct uvc_video_queue queue;
unsigned int fid;
};
enum uvc_state
{
UVC_STATE_DISCONNECTED,
UVC_STATE_CONNECTED,
UVC_STATE_STREAMING,
};
struct uvc_device
{
struct video_device *vdev;
enum uvc_state state;
struct usb_function func;
struct uvc_video video;
/* Descriptors */
struct {
const struct uvc_descriptor_header * const *control;
const struct uvc_descriptor_header * const *fs_streaming;
const struct uvc_descriptor_header * const *hs_streaming;
} desc;
unsigned int control_intf;
struct usb_ep *control_ep;
struct usb_request *control_req;
void *control_buf;
unsigned int streaming_intf;
/* Events */
unsigned int event_length;
unsigned int event_setup_out : 1;
};
static inline struct uvc_device *to_uvc(struct usb_function *f)
{
return container_of(f, struct uvc_device, func);
}
struct uvc_file_handle
{
struct v4l2_fh vfh;
struct uvc_video *device;
};
#define to_uvc_file_handle(handle) \
container_of(handle, struct uvc_file_handle, vfh)
extern struct v4l2_file_operations uvc_v4l2_fops;
/* ------------------------------------------------------------------------
* Functions
*/
extern int uvc_video_enable(struct uvc_video *video, int enable);
extern int uvc_video_init(struct uvc_video *video);
extern int uvc_video_pump(struct uvc_video *video);
extern void uvc_endpoint_stream(struct uvc_device *dev);
extern void uvc_function_connect(struct uvc_device *uvc);
extern void uvc_function_disconnect(struct uvc_device *uvc);
#endif /* __KERNEL__ */
#endif /* _UVC_GADGET_H_ */

View File

@ -0,0 +1,583 @@
/*
* uvc_queue.c -- USB Video Class driver - Buffers management
*
* Copyright (C) 2005-2010
* Laurent Pinchart (laurent.pinchart@ideasonboard.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.
*
*/
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <asm/atomic.h>
#include "uvc.h"
/* ------------------------------------------------------------------------
* Video buffers queue management.
*
* Video queues is initialized by uvc_queue_init(). The function performs
* basic initialization of the uvc_video_queue struct and never fails.
*
* Video buffer allocation and freeing are performed by uvc_alloc_buffers and
* uvc_free_buffers respectively. The former acquires the video queue lock,
* while the later must be called with the lock held (so that allocation can
* free previously allocated buffers). Trying to free buffers that are mapped
* to user space will return -EBUSY.
*
* Video buffers are managed using two queues. However, unlike most USB video
* drivers that use an in queue and an out queue, we use a main queue to hold
* all queued buffers (both 'empty' and 'done' buffers), and an irq queue to
* hold empty buffers. This design (copied from video-buf) minimizes locking
* in interrupt, as only one queue is shared between interrupt and user
* contexts.
*
* Use cases
* ---------
*
* Unless stated otherwise, all operations that modify the irq buffers queue
* are protected by the irq spinlock.
*
* 1. The user queues the buffers, starts streaming and dequeues a buffer.
*
* The buffers are added to the main and irq queues. Both operations are
* protected by the queue lock, and the later is protected by the irq
* spinlock as well.
*
* The completion handler fetches a buffer from the irq queue and fills it
* with video data. If no buffer is available (irq queue empty), the handler
* returns immediately.
*
* When the buffer is full, the completion handler removes it from the irq
* queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue.
* At that point, any process waiting on the buffer will be woken up. If a
* process tries to dequeue a buffer after it has been marked ready, the
* dequeing will succeed immediately.
*
* 2. Buffers are queued, user is waiting on a buffer and the device gets
* disconnected.
*
* When the device is disconnected, the kernel calls the completion handler
* with an appropriate status code. The handler marks all buffers in the
* irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so
* that any process waiting on a buffer gets woken up.
*
* Waking up up the first buffer on the irq list is not enough, as the
* process waiting on the buffer might restart the dequeue operation
* immediately.
*
*/
void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
{
mutex_init(&queue->mutex);
spin_lock_init(&queue->irqlock);
INIT_LIST_HEAD(&queue->mainqueue);
INIT_LIST_HEAD(&queue->irqqueue);
queue->type = type;
}
/*
* Allocate the video buffers.
*
* Pages are reserved to make sure they will not be swapped, as they will be
* filled in the URB completion handler.
*
* Buffers will be individually mapped, so they must all be page aligned.
*/
int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
unsigned int buflength)
{
unsigned int bufsize = PAGE_ALIGN(buflength);
unsigned int i;
void *mem = NULL;
int ret;
if (nbuffers > UVC_MAX_VIDEO_BUFFERS)
nbuffers = UVC_MAX_VIDEO_BUFFERS;
mutex_lock(&queue->mutex);
if ((ret = uvc_free_buffers(queue)) < 0)
goto done;
/* Bail out if no buffers should be allocated. */
if (nbuffers == 0)
goto done;
/* Decrement the number of buffers until allocation succeeds. */
for (; nbuffers > 0; --nbuffers) {
mem = vmalloc_32(nbuffers * bufsize);
if (mem != NULL)
break;
}
if (mem == NULL) {
ret = -ENOMEM;
goto done;
}
for (i = 0; i < nbuffers; ++i) {
memset(&queue->buffer[i], 0, sizeof queue->buffer[i]);
queue->buffer[i].buf.index = i;
queue->buffer[i].buf.m.offset = i * bufsize;
queue->buffer[i].buf.length = buflength;
queue->buffer[i].buf.type = queue->type;
queue->buffer[i].buf.sequence = 0;
queue->buffer[i].buf.field = V4L2_FIELD_NONE;
queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP;
queue->buffer[i].buf.flags = 0;
init_waitqueue_head(&queue->buffer[i].wait);
}
queue->mem = mem;
queue->count = nbuffers;
queue->buf_size = bufsize;
ret = nbuffers;
done:
mutex_unlock(&queue->mutex);
return ret;
}
/*
* Free the video buffers.
*
* This function must be called with the queue lock held.
*/
int uvc_free_buffers(struct uvc_video_queue *queue)
{
unsigned int i;
for (i = 0; i < queue->count; ++i) {
if (queue->buffer[i].vma_use_count != 0)
return -EBUSY;
}
if (queue->count) {
vfree(queue->mem);
queue->count = 0;
}
return 0;
}
static void __uvc_query_buffer(struct uvc_buffer *buf,
struct v4l2_buffer *v4l2_buf)
{
memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);
if (buf->vma_use_count)
v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED;
switch (buf->state) {
case UVC_BUF_STATE_ERROR:
case UVC_BUF_STATE_DONE:
v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;
break;
case UVC_BUF_STATE_QUEUED:
case UVC_BUF_STATE_ACTIVE:
v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
break;
case UVC_BUF_STATE_IDLE:
default:
break;
}
}
int uvc_query_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf)
{
int ret = 0;
mutex_lock(&queue->mutex);
if (v4l2_buf->index >= queue->count) {
ret = -EINVAL;
goto done;
}
__uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
done:
mutex_unlock(&queue->mutex);
return ret;
}
/*
* Queue a video buffer. Attempting to queue a buffer that has already been
* queued will return -EINVAL.
*/
int uvc_queue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf)
{
struct uvc_buffer *buf;
unsigned long flags;
int ret = 0;
uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index);
if (v4l2_buf->type != queue->type ||
v4l2_buf->memory != V4L2_MEMORY_MMAP) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
"and/or memory (%u).\n", v4l2_buf->type,
v4l2_buf->memory);
return -EINVAL;
}
mutex_lock(&queue->mutex);
if (v4l2_buf->index >= queue->count) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n");
ret = -EINVAL;
goto done;
}
buf = &queue->buffer[v4l2_buf->index];
if (buf->state != UVC_BUF_STATE_IDLE) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state "
"(%u).\n", buf->state);
ret = -EINVAL;
goto done;
}
if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
v4l2_buf->bytesused > buf->buf.length) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
ret = -EINVAL;
goto done;
}
if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
buf->buf.bytesused = 0;
else
buf->buf.bytesused = v4l2_buf->bytesused;
spin_lock_irqsave(&queue->irqlock, flags);
if (queue->flags & UVC_QUEUE_DISCONNECTED) {
spin_unlock_irqrestore(&queue->irqlock, flags);
ret = -ENODEV;
goto done;
}
buf->state = UVC_BUF_STATE_QUEUED;
ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
queue->flags &= ~UVC_QUEUE_PAUSED;
list_add_tail(&buf->stream, &queue->mainqueue);
list_add_tail(&buf->queue, &queue->irqqueue);
spin_unlock_irqrestore(&queue->irqlock, flags);
done:
mutex_unlock(&queue->mutex);
return ret;
}
static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
{
if (nonblocking) {
return (buf->state != UVC_BUF_STATE_QUEUED &&
buf->state != UVC_BUF_STATE_ACTIVE)
? 0 : -EAGAIN;
}
return wait_event_interruptible(buf->wait,
buf->state != UVC_BUF_STATE_QUEUED &&
buf->state != UVC_BUF_STATE_ACTIVE);
}
/*
* Dequeue a video buffer. If nonblocking is false, block until a buffer is
* available.
*/
int uvc_dequeue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf, int nonblocking)
{
struct uvc_buffer *buf;
int ret = 0;
if (v4l2_buf->type != queue->type ||
v4l2_buf->memory != V4L2_MEMORY_MMAP) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
"and/or memory (%u).\n", v4l2_buf->type,
v4l2_buf->memory);
return -EINVAL;
}
mutex_lock(&queue->mutex);
if (list_empty(&queue->mainqueue)) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n");
ret = -EINVAL;
goto done;
}
buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0)
goto done;
uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n",
buf->buf.index, buf->state, buf->buf.bytesused);
switch (buf->state) {
case UVC_BUF_STATE_ERROR:
uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data "
"(transmission error).\n");
ret = -EIO;
case UVC_BUF_STATE_DONE:
buf->state = UVC_BUF_STATE_IDLE;
break;
case UVC_BUF_STATE_IDLE:
case UVC_BUF_STATE_QUEUED:
case UVC_BUF_STATE_ACTIVE:
default:
uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u "
"(driver bug?).\n", buf->state);
ret = -EINVAL;
goto done;
}
list_del(&buf->stream);
__uvc_query_buffer(buf, v4l2_buf);
done:
mutex_unlock(&queue->mutex);
return ret;
}
/*
* Poll the video queue.
*
* This function implements video queue polling and is intended to be used by
* the device poll handler.
*/
unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
poll_table *wait)
{
struct uvc_buffer *buf;
unsigned int mask = 0;
mutex_lock(&queue->mutex);
if (list_empty(&queue->mainqueue))
goto done;
buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
poll_wait(file, &buf->wait, wait);
if (buf->state == UVC_BUF_STATE_DONE ||
buf->state == UVC_BUF_STATE_ERROR)
mask |= POLLOUT | POLLWRNORM;
done:
mutex_unlock(&queue->mutex);
return mask;
}
/*
* VMA operations.
*/
static void uvc_vm_open(struct vm_area_struct *vma)
{
struct uvc_buffer *buffer = vma->vm_private_data;
buffer->vma_use_count++;
}
static void uvc_vm_close(struct vm_area_struct *vma)
{
struct uvc_buffer *buffer = vma->vm_private_data;
buffer->vma_use_count--;
}
static struct vm_operations_struct uvc_vm_ops = {
.open = uvc_vm_open,
.close = uvc_vm_close,
};
/*
* Memory-map a buffer.
*
* This function implements video buffer memory mapping and is intended to be
* used by the device mmap handler.
*/
int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
{
struct uvc_buffer *uninitialized_var(buffer);
struct page *page;
unsigned long addr, start, size;
unsigned int i;
int ret = 0;
start = vma->vm_start;
size = vma->vm_end - vma->vm_start;
mutex_lock(&queue->mutex);
for (i = 0; i < queue->count; ++i) {
buffer = &queue->buffer[i];
if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
break;
}
if (i == queue->count || size != queue->buf_size) {
ret = -EINVAL;
goto done;
}
/*
* VM_IO marks the area as being an mmaped region for I/O to a
* device. It also prevents the region from being core dumped.
*/
vma->vm_flags |= VM_IO;
addr = (unsigned long)queue->mem + buffer->buf.m.offset;
while (size > 0) {
page = vmalloc_to_page((void *)addr);
if ((ret = vm_insert_page(vma, start, page)) < 0)
goto done;
start += PAGE_SIZE;
addr += PAGE_SIZE;
size -= PAGE_SIZE;
}
vma->vm_ops = &uvc_vm_ops;
vma->vm_private_data = buffer;
uvc_vm_open(vma);
done:
mutex_unlock(&queue->mutex);
return ret;
}
/*
* Enable or disable the video buffers queue.
*
* The queue must be enabled before starting video acquisition and must be
* disabled after stopping it. This ensures that the video buffers queue
* state can be properly initialized before buffers are accessed from the
* interrupt handler.
*
* Enabling the video queue initializes parameters (such as sequence number,
* sync pattern, ...). If the queue is already enabled, return -EBUSY.
*
* Disabling the video queue cancels the queue and removes all buffers from
* the main queue.
*
* This function can't be called from interrupt context. Use
* uvc_queue_cancel() instead.
*/
int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
{
unsigned int i;
int ret = 0;
mutex_lock(&queue->mutex);
if (enable) {
if (uvc_queue_streaming(queue)) {
ret = -EBUSY;
goto done;
}
queue->sequence = 0;
queue->flags |= UVC_QUEUE_STREAMING;
queue->buf_used = 0;
} else {
uvc_queue_cancel(queue, 0);
INIT_LIST_HEAD(&queue->mainqueue);
for (i = 0; i < queue->count; ++i)
queue->buffer[i].state = UVC_BUF_STATE_IDLE;
queue->flags &= ~UVC_QUEUE_STREAMING;
}
done:
mutex_unlock(&queue->mutex);
return ret;
}
/*
* Cancel the video buffers queue.
*
* Cancelling the queue marks all buffers on the irq queue as erroneous,
* wakes them up and removes them from the queue.
*
* If the disconnect parameter is set, further calls to uvc_queue_buffer will
* fail with -ENODEV.
*
* This function acquires the irq spinlock and can be called from interrupt
* context.
*/
void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
{
struct uvc_buffer *buf;
unsigned long flags;
spin_lock_irqsave(&queue->irqlock, flags);
while (!list_empty(&queue->irqqueue)) {
buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
list_del(&buf->queue);
buf->state = UVC_BUF_STATE_ERROR;
wake_up(&buf->wait);
}
/* This must be protected by the irqlock spinlock to avoid race
* conditions between uvc_queue_buffer and the disconnection event that
* could result in an interruptible wait in uvc_dequeue_buffer. Do not
* blindly replace this logic by checking for the UVC_DEV_DISCONNECTED
* state outside the queue code.
*/
if (disconnect)
queue->flags |= UVC_QUEUE_DISCONNECTED;
spin_unlock_irqrestore(&queue->irqlock, flags);
}
struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *buf)
{
struct uvc_buffer *nextbuf;
unsigned long flags;
if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
buf->buf.length != buf->buf.bytesused) {
buf->state = UVC_BUF_STATE_QUEUED;
buf->buf.bytesused = 0;
return buf;
}
spin_lock_irqsave(&queue->irqlock, flags);
list_del(&buf->queue);
if (!list_empty(&queue->irqqueue))
nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
else
nextbuf = NULL;
spin_unlock_irqrestore(&queue->irqlock, flags);
buf->buf.sequence = queue->sequence++;
do_gettimeofday(&buf->buf.timestamp);
wake_up(&buf->wait);
return nextbuf;
}
struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue)
{
struct uvc_buffer *buf = NULL;
if (!list_empty(&queue->irqqueue))
buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
else
queue->flags |= UVC_QUEUE_PAUSED;
return buf;
}

View File

@ -0,0 +1,89 @@
#ifndef _UVC_QUEUE_H_
#define _UVC_QUEUE_H_
#ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/videodev2.h>
/* Maximum frame size in bytes, for sanity checking. */
#define UVC_MAX_FRAME_SIZE (16*1024*1024)
/* Maximum number of video buffers. */
#define UVC_MAX_VIDEO_BUFFERS 32
/* ------------------------------------------------------------------------
* Structures.
*/
enum uvc_buffer_state {
UVC_BUF_STATE_IDLE = 0,
UVC_BUF_STATE_QUEUED = 1,
UVC_BUF_STATE_ACTIVE = 2,
UVC_BUF_STATE_DONE = 3,
UVC_BUF_STATE_ERROR = 4,
};
struct uvc_buffer {
unsigned long vma_use_count;
struct list_head stream;
/* Touched by interrupt handler. */
struct v4l2_buffer buf;
struct list_head queue;
wait_queue_head_t wait;
enum uvc_buffer_state state;
};
#define UVC_QUEUE_STREAMING (1 << 0)
#define UVC_QUEUE_DISCONNECTED (1 << 1)
#define UVC_QUEUE_DROP_INCOMPLETE (1 << 2)
#define UVC_QUEUE_PAUSED (1 << 3)
struct uvc_video_queue {
enum v4l2_buf_type type;
void *mem;
unsigned int flags;
__u32 sequence;
unsigned int count;
unsigned int buf_size;
unsigned int buf_used;
struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS];
struct mutex mutex; /* protects buffers and mainqueue */
spinlock_t irqlock; /* protects irqqueue */
struct list_head mainqueue;
struct list_head irqqueue;
};
extern void uvc_queue_init(struct uvc_video_queue *queue,
enum v4l2_buf_type type);
extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
unsigned int nbuffers, unsigned int buflength);
extern int uvc_free_buffers(struct uvc_video_queue *queue);
extern int uvc_query_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf);
extern int uvc_queue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf);
extern int uvc_dequeue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf, int nonblocking);
extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *buf);
extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
struct file *file, poll_table *wait);
extern int uvc_queue_mmap(struct uvc_video_queue *queue,
struct vm_area_struct *vma);
static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
{
return queue->flags & UVC_QUEUE_STREAMING;
}
extern struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue);
#endif /* __KERNEL__ */
#endif /* _UVC_QUEUE_H_ */

Some files were not shown because too many files have changed in this diff Show More