LWN.net Logo

g_my_mass.c

/******************** Includes ********************/
#include <linux/kernel.h>
#include <linux/usb/ch9.h>

#include "composite.c"
#include "usbstring.c"
#include "config.c"
#include "epautoconf.c"

#include "f_mass_storage.c"


/******************** Standard Module Stuff ********************/
#define MSG_DRIVER_DESC     "My Own Mass Storage Gadget"
#define MSG_DRIVER_VERSION  "2010/06/11"

MODULE_DESCRIPTION(MSG_DRIVER_DESC);
MODULE_AUTHOR("Michal Nazarewicz");
MODULE_LICENSE("GPL");


static int __ref msg_do_config(struct usb_configuration *c);
static void msg_exit(void);


/******************** Device Descriptor ********************/
static struct usb_device_descriptor msg_dev_desc = {
	.bLength =		sizeof msg_dev_desc,
	.bDescriptorType =	USB_DT_DEVICE,
	.bcdUSB =		cpu_to_le16(0x0200),
	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
	.idVendor =		cpu_to_le16(FSG_VENDOR_ID),
	.idProduct =		cpu_to_le16(FSG_PRODUCT_ID),
};


/******************** Configuration ********************/
static struct usb_configuration msg_config = {
	.label			= "Linux Mass Storage",
	.bind			= msg_do_config,
	.bConfigurationValue	= 1,
	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
};


/******************** Mass Storage Function ********************/
static struct fsg_module_parameters msg_mod_data = { .stall = 1 };
FSG_MODULE_PARAMETERS(/* no prefix */, msg_mod_data);

static struct fsg_common msg_fsg_common;

static int msg_thread_exits(struct fsg_common *common)
{
	msg_exit();
	return 0;
}

static int msg_fsg_init(struct usb_composite_dev *cdev)
{
	struct fsg_config config;
	struct fsg_common *retp;

	fsg_config_from_params(&config, &msg_mod_data);

	config.thread_exits = msg_thread_exits;

	retp = fsg_common_init(&msg_fsg_common, cdev, &config);
	return IS_ERR(retp) ? PTR_ERR(retp) : 0;
}


/******************** Device Bind Function ********************/
static unsigned long msg_registered;

static int __ref msg_bind(struct usb_composite_dev *cdev)
{
	int ret;

	ret = msg_fsg_init(cdev);
	if (ret < 0)
		return ret;

	ret = usb_add_config(cdev, &msg_config);
	if (ret >= 0)
		set_bit(0, &msg_registered);
	fsg_common_put(&msg_fsg_common);
	return ret;
}


/******************** Configuration Bind Function ********************/
static int __ref msg_do_config(struct usb_configuration *c)
{
	return fsg_add(c->cdev, c, &msg_fsg_common);
}


/******************** Composite Device ********************/
static struct usb_composite_driver msg_device = {
	.name		= "g_my_mass_storage",
	.dev		= &msg_dev_desc,
	.bind		= msg_bind,
};


/******************** Module Init/Exit ********************/
static int __init msg_init(void)
{
	return usb_composite_register(&msg_device);
}
module_init(msg_init);

static void msg_exit(void)
{
	if (test_and_clear_bit(0, &msg_registered))
		usb_composite_unregister(&msg_device);
}
module_exit(msg_exit);

(Log in to post comments)

Copyright © 2010, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds