zero.c 9.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 * zero.c -- Gadget Zero, for USB development
 *
4 5
 * Copyright (C) 2003-2008 David Brownell
 * Copyright (C) 2008 by Nokia Corporation
L
Linus Torvalds 已提交
6
 *
D
David Brownell 已提交
7 8 9 10
 * 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.
L
Linus Torvalds 已提交
11 12 13 14 15 16
 */


/*
 * Gadget Zero only needs two bulk endpoints, and is an example of how you
 * can write a hardware-agnostic gadget driver running inside a USB device.
17
 * Some hardware details are visible, but don't affect most of the driver.
L
Linus Torvalds 已提交
18 19 20 21 22 23
 *
 * Use it with the Linux host/master side "usbtest" driver to get a basic
 * functional test of your device-side usb stack, or with "usb-skeleton".
 *
 * It supports two similar configurations.  One sinks whatever the usb host
 * writes, and in return sources zeroes.  The other loops whatever the host
24
 * writes back, so the host can read it.
L
Linus Torvalds 已提交
25 26 27 28
 *
 * Many drivers will only have one configuration, letting them be much
 * simpler if they also don't support high speed operation (like this
 * driver does).
D
David Brownell 已提交
29 30 31 32 33
 *
 * Why is *this* driver using two configurations, rather than setting up
 * two interfaces with different functions?  To help verify that multiple
 * configuration infrastucture is working correctly; also, so that it can
 * work with low capability USB controllers without four bulk endpoints.
L
Linus Torvalds 已提交
34 35
 */

36 37 38 39 40
/*
 * driver assumes self-powered hardware, and
 * has no way for users to trigger remote wakeup.
 */

D
David Brownell 已提交
41
/* #define VERBOSE_DEBUG */
L
Linus Torvalds 已提交
42 43

#include <linux/kernel.h>
44
#include <linux/slab.h>
L
Linus Torvalds 已提交
45 46 47
#include <linux/utsname.h>
#include <linux/device.h>

48
#include "g_zero.h"
L
Linus Torvalds 已提交
49 50 51
#include "gadget_chips.h"


52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
/*-------------------------------------------------------------------------*/

/*
 * 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_sourcesink.c"
#include "f_loopback.c"

L
Linus Torvalds 已提交
69 70
/*-------------------------------------------------------------------------*/

71
#define DRIVER_VERSION		"Cinco de Mayo 2008"
L
Linus Torvalds 已提交
72

73
static const char longname[] = "Gadget Zero";
L
Linus Torvalds 已提交
74

75
unsigned buflen = 4096;		/* only used for bulk endpoints */
76
module_param(buflen, uint, 0);
L
Linus Torvalds 已提交
77 78 79 80

/*
 * Normally the "loopback" configuration is second (index 1) so
 * it's not the default.  Here's where to change that order, to
81 82
 * work better with hosts where config changes are problematic or
 * controllers (like original superh) that only support one config.
L
Linus Torvalds 已提交
83
 */
84
static bool loopdefault = 0;
85
module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
L
Linus Torvalds 已提交
86 87 88 89 90 91 92 93 94 95 96

/*-------------------------------------------------------------------------*/

/* Thanks to NetChip Technologies for donating this product ID.
 *
 * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
 * Instead:  allocate your own, using normal USB-IF procedures.
 */
#ifndef	CONFIG_USB_ZERO_HNPTEST
#define DRIVER_VENDOR_NUM	0x0525		/* NetChip */
#define DRIVER_PRODUCT_NUM	0xa4a0		/* Linux-USB "Gadget Zero" */
97
#define DEFAULT_AUTORESUME	0
L
Linus Torvalds 已提交
98 99 100
#else
#define DRIVER_VENDOR_NUM	0x1a0a		/* OTG test device IDs */
#define DRIVER_PRODUCT_NUM	0xbadd
101
#define DEFAULT_AUTORESUME	5
L
Linus Torvalds 已提交
102 103
#endif

104 105 106 107 108 109 110 111
/* If the optional "autoresume" mode is enabled, it provides good
 * functional coverage for the "USBCV" test harness from USB-IF.
 * It's always set if OTG mode is enabled.
 */
unsigned autoresume = DEFAULT_AUTORESUME;
module_param(autoresume, uint, S_IRUGO);
MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");

L
Linus Torvalds 已提交
112 113
/*-------------------------------------------------------------------------*/

114
static struct usb_device_descriptor device_desc = {
L
Linus Torvalds 已提交
115 116 117
	.bLength =		sizeof device_desc,
	.bDescriptorType =	USB_DT_DEVICE,

118
	.bcdUSB =		cpu_to_le16(0x0200),
L
Linus Torvalds 已提交
119 120
	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,

121 122
	.idVendor =		cpu_to_le16(DRIVER_VENDOR_NUM),
	.idProduct =		cpu_to_le16(DRIVER_PRODUCT_NUM),
L
Linus Torvalds 已提交
123 124 125
	.bNumConfigurations =	2,
};

126
#ifdef CONFIG_USB_OTG
127
static struct usb_otg_descriptor otg_descriptor = {
L
Linus Torvalds 已提交
128 129 130
	.bLength =		sizeof otg_descriptor,
	.bDescriptorType =	USB_DT_OTG,

131 132 133 134
	/* REVISIT SRP-only hardware is possible, although
	 * it would not be called "OTG" ...
	 */
	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
L
Linus Torvalds 已提交
135 136
};

137
const struct usb_descriptor_header *otg_desc[] = {
L
Linus Torvalds 已提交
138 139 140
	(struct usb_descriptor_header *) &otg_descriptor,
	NULL,
};
141
#endif
L
Linus Torvalds 已提交
142

143
/* string IDs are assigned dynamically */
L
Linus Torvalds 已提交
144

145 146 147
#define STRING_MANUFACTURER_IDX		0
#define STRING_PRODUCT_IDX		1
#define STRING_SERIAL_IDX		2
L
Linus Torvalds 已提交
148

D
David Brownell 已提交
149
static char manufacturer[50];
L
Linus Torvalds 已提交
150

D
David Brownell 已提交
151 152
/* default serial number takes at least two packets */
static char serial[] = "0123456789.0123456789.0123456789";
L
Linus Torvalds 已提交
153

154 155 156 157
static struct usb_string strings_dev[] = {
	[STRING_MANUFACTURER_IDX].s = manufacturer,
	[STRING_PRODUCT_IDX].s = longname,
	[STRING_SERIAL_IDX].s = serial,
L
Linus Torvalds 已提交
158 159 160
	{  }			/* end of list */
};

161
static struct usb_gadget_strings stringtab_dev = {
L
Linus Torvalds 已提交
162
	.language	= 0x0409,	/* en-us */
163
	.strings	= strings_dev,
L
Linus Torvalds 已提交
164 165
};

166 167 168 169
static struct usb_gadget_strings *dev_strings[] = {
	&stringtab_dev,
	NULL,
};
L
Linus Torvalds 已提交
170 171 172

/*-------------------------------------------------------------------------*/

173
struct usb_request *alloc_ep_req(struct usb_ep *ep, int len)
L
Linus Torvalds 已提交
174 175 176
{
	struct usb_request	*req;

177
	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
L
Linus Torvalds 已提交
178
	if (req) {
179 180 181 182 183
		if (len)
			req->length = len;
		else
			req->length = buflen;
		req->buf = kmalloc(req->length, GFP_ATOMIC);
L
Linus Torvalds 已提交
184
		if (!req->buf) {
185
			usb_ep_free_request(ep, req);
L
Linus Torvalds 已提交
186 187 188 189 190 191
			req = NULL;
		}
	}
	return req;
}

192
void free_ep_req(struct usb_ep *ep, struct usb_request *req)
L
Linus Torvalds 已提交
193
{
194
	kfree(req->buf);
195
	usb_ep_free_request(ep, req);
L
Linus Torvalds 已提交
196 197
}

198
static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
L
Linus Torvalds 已提交
199
{
200 201 202 203 204 205 206 207
	int			value;

	if (ep->driver_data) {
		value = usb_ep_disable(ep);
		if (value < 0)
			DBG(cdev, "disable %s --> %d\n",
					ep->name, value);
		ep->driver_data = NULL;
L
Linus Torvalds 已提交
208 209 210
	}
}

211
void disable_endpoints(struct usb_composite_dev *cdev,
212 213
		struct usb_ep *in, struct usb_ep *out,
		struct usb_ep *iso_in, struct usb_ep *iso_out)
L
Linus Torvalds 已提交
214
{
215 216
	disable_ep(cdev, in);
	disable_ep(cdev, out);
217 218 219 220
	if (iso_in)
		disable_ep(cdev, iso_in);
	if (iso_out)
		disable_ep(cdev, iso_out);
L
Linus Torvalds 已提交
221 222 223 224
}

/*-------------------------------------------------------------------------*/

225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
static struct timer_list	autoresume_timer;

static void zero_autoresume(unsigned long _c)
{
	struct usb_composite_dev	*cdev = (void *)_c;
	struct usb_gadget		*g = cdev->gadget;

	/* unconfigured devices can't issue wakeups */
	if (!cdev->config)
		return;

	/* Normally the host would be woken up for something
	 * more significant than just a timer firing; likely
	 * because of some direct user request.
	 */
	if (g->speed != USB_SPEED_UNKNOWN) {
		int status = usb_gadget_wakeup(g);
		INFO(cdev, "%s --> %d\n", __func__, status);
	}
}

static void zero_suspend(struct usb_composite_dev *cdev)
{
	if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
		return;

	if (autoresume) {
		mod_timer(&autoresume_timer, jiffies + (HZ * autoresume));
		DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume);
	} else
		DBG(cdev, "%s\n", __func__);
}

static void zero_resume(struct usb_composite_dev *cdev)
{
	DBG(cdev, "%s\n", __func__);
	del_timer(&autoresume_timer);
}

/*-------------------------------------------------------------------------*/

266
static int __init zero_bind(struct usb_composite_dev *cdev)
L
Linus Torvalds 已提交
267
{
268
	int			gcnum;
269 270
	struct usb_gadget	*gadget = cdev->gadget;
	int			id;
271

272 273
	/* Allocate string descriptor numbers ... note that string
	 * contents can be overridden by the composite_dev glue.
274
	 */
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
	id = usb_string_id(cdev);
	if (id < 0)
		return id;
	strings_dev[STRING_MANUFACTURER_IDX].id = id;
	device_desc.iManufacturer = id;

	id = usb_string_id(cdev);
	if (id < 0)
		return id;
	strings_dev[STRING_PRODUCT_IDX].id = id;
	device_desc.iProduct = id;

	id = usb_string_id(cdev);
	if (id < 0)
		return id;
	strings_dev[STRING_SERIAL_IDX].id = id;
	device_desc.iSerialNumber = id;

293 294
	setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);

295 296
	/* Register primary, then secondary configuration.  Note that
	 * SH3 only allows one config...
L
Linus Torvalds 已提交
297
	 */
298
	if (loopdefault) {
299
		loopback_add(cdev, autoresume != 0);
300
		sourcesink_add(cdev, autoresume != 0);
301
	} else {
302
		sourcesink_add(cdev, autoresume != 0);
303
		loopback_add(cdev, autoresume != 0);
L
Linus Torvalds 已提交
304 305
	}

306
	gcnum = usb_gadget_controller_number(gadget);
307
	if (gcnum >= 0)
308
		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
309
	else {
L
Linus Torvalds 已提交
310 311
		/* gadget zero is so simple (for now, no altsettings) that
		 * it SHOULD NOT have problems with bulk-capable hardware.
312
		 * so just warn about unrcognized controllers -- don't panic.
L
Linus Torvalds 已提交
313 314 315 316
		 *
		 * things like configuration and altsetting numbering
		 * can need hardware-specific attention though.
		 */
317
		pr_warning("%s: controller '%s' not recognized\n",
318
			longname, gadget->name);
319
		device_desc.bcdDevice = cpu_to_le16(0x9999);
L
Linus Torvalds 已提交
320 321
	}

322
	INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);
L
Linus Torvalds 已提交
323

324
	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
325
		init_utsname()->sysname, init_utsname()->release,
L
Linus Torvalds 已提交
326 327 328 329 330
		gadget->name);

	return 0;
}

331 332 333 334 335 336
static int zero_unbind(struct usb_composite_dev *cdev)
{
	del_timer_sync(&autoresume_timer);
	return 0;
}

337 338 339 340
static struct usb_composite_driver zero_driver = {
	.name		= "zero",
	.dev		= &device_desc,
	.strings	= dev_strings,
341
	.max_speed	= USB_SPEED_SUPER,
342 343 344
	.unbind		= zero_unbind,
	.suspend	= zero_suspend,
	.resume		= zero_resume,
L
Linus Torvalds 已提交
345 346
};

D
David Brownell 已提交
347 348
MODULE_AUTHOR("David Brownell");
MODULE_LICENSE("GPL");
L
Linus Torvalds 已提交
349

350
static int __init init(void)
L
Linus Torvalds 已提交
351
{
352
	return usb_composite_probe(&zero_driver, zero_bind);
L
Linus Torvalds 已提交
353
}
354
module_init(init);
L
Linus Torvalds 已提交
355

356
static void __exit cleanup(void)
L
Linus Torvalds 已提交
357
{
358
	usb_composite_unregister(&zero_driver);
L
Linus Torvalds 已提交
359
}
360
module_exit(cleanup);