diff options
| -rw-r--r-- | README | 7 | ||||
| -rw-r--r-- | board/samsung/common/Makefile | 1 | ||||
| -rw-r--r-- | board/samsung/common/ums.c | 76 | ||||
| -rw-r--r-- | board/samsung/trats/trats.c | 62 | ||||
| -rw-r--r-- | common/cmd_usb_mass_storage.c | 51 | ||||
| -rw-r--r-- | drivers/dfu/dfu.c | 3 | ||||
| -rw-r--r-- | drivers/dfu/dfu_nand.c | 1 | ||||
| -rw-r--r-- | drivers/usb/gadget/f_mass_storage.c | 67 | ||||
| -rw-r--r-- | drivers/usb/gadget/g_dnl.c | 20 | ||||
| -rw-r--r-- | drivers/usb/gadget/storage_common.c | 27 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-hcd.c | 2 | ||||
| -rw-r--r-- | include/configs/trats.h | 2 | ||||
| -rw-r--r-- | include/g_dnl.h | 1 | ||||
| -rw-r--r-- | include/usb.h | 10 | ||||
| -rw-r--r-- | include/usb_mass_storage.h | 33 | 
15 files changed, 205 insertions, 158 deletions
| @@ -1367,6 +1367,13 @@ The following options need to be configured:  			for your device  			- CONFIG_USBD_PRODUCTID 0xFFFF +		Some USB device drivers may need to check USB cable attachment. +		In this case you can enable following config in BoardName.h: +			CONFIG_USB_CABLE_CHECK +			This enables function definition: +			- usb_cable_connected() in include/usb.h +			Implementation of this function is board-specific. +  - ULPI Layer Support:  		The ULPI (UTMI Low Pin (count) Interface) PHYs are supported via  		the generic ULPI layer. The generic layer accesses the ULPI PHY diff --git a/board/samsung/common/Makefile b/board/samsung/common/Makefile index ca7032c3d..501d9744e 100644 --- a/board/samsung/common/Makefile +++ b/board/samsung/common/Makefile @@ -7,3 +7,4 @@  obj-$(CONFIG_SOFT_I2C_MULTI_BUS) += multi_i2c.o  obj-$(CONFIG_THOR_FUNCTION) += thor.o +obj-$(CONFIG_CMD_USB_MASS_STORAGE) += ums.o diff --git a/board/samsung/common/ums.c b/board/samsung/common/ums.c new file mode 100644 index 000000000..dc155ad0e --- /dev/null +++ b/board/samsung/common/ums.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013 Samsung Electronics + * Lukasz Majewski <l.majewski@samsung.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <usb_mass_storage.h> +#include <part.h> + +static int ums_read_sector(struct ums *ums_dev, +			   ulong start, lbaint_t blkcnt, void *buf) +{ +	block_dev_desc_t *block_dev = &ums_dev->mmc->block_dev; +	lbaint_t blkstart = start + ums_dev->start_sector; +	int dev_num = block_dev->dev; + +	return block_dev->block_read(dev_num, blkstart, blkcnt, buf); +} + +static int ums_write_sector(struct ums *ums_dev, +			    ulong start, lbaint_t blkcnt, const void *buf) +{ +	block_dev_desc_t *block_dev = &ums_dev->mmc->block_dev; +	lbaint_t blkstart = start + ums_dev->start_sector; +	int dev_num = block_dev->dev; + +	return block_dev->block_write(dev_num, blkstart, blkcnt, buf); +} + +static struct ums ums_dev = { +	.read_sector = ums_read_sector, +	.write_sector = ums_write_sector, +	.name = "UMS disk", +}; + +static struct ums *ums_disk_init(struct mmc *mmc) +{ +	uint64_t mmc_end_sector = mmc->capacity / SECTOR_SIZE; +	uint64_t ums_end_sector = UMS_NUM_SECTORS + UMS_START_SECTOR; + +	if (!mmc_end_sector) { +		error("MMC capacity is not valid"); +		return NULL; +	} + +	ums_dev.mmc = mmc; + +	if (ums_end_sector <= mmc_end_sector) { +		ums_dev.start_sector = UMS_START_SECTOR; +		if (UMS_NUM_SECTORS) +			ums_dev.num_sectors = UMS_NUM_SECTORS; +		else +			ums_dev.num_sectors = mmc_end_sector - UMS_START_SECTOR; +	} else { +		ums_dev.num_sectors = mmc_end_sector; +		puts("UMS: defined bad disk parameters. Using default.\n"); +	} + +	printf("UMS: disk start sector: %#x, count: %#x\n", +	       ums_dev.start_sector, ums_dev.num_sectors); + +	return &ums_dev; +} + +struct ums *ums_init(unsigned int dev_num) +{ +	struct mmc *mmc = NULL; + +	mmc = find_mmc_device(dev_num); +	if (!mmc) +		return NULL; + +	return ums_disk_init(mmc); +} diff --git a/board/samsung/trats/trats.c b/board/samsung/trats/trats.c index d31d511e3..7012c134f 100644 --- a/board/samsung/trats/trats.c +++ b/board/samsung/trats/trats.c @@ -772,65 +772,3 @@ void init_panel_info(vidinfo_t *vid)  	setenv("lcdinfo", "lcd=s6e8ax0");  } - -#ifdef CONFIG_USB_GADGET_MASS_STORAGE -static int ums_read_sector(struct ums_device *ums_dev, -			   ulong start, lbaint_t blkcnt, void *buf) -{ -	if (ums_dev->mmc->block_dev.block_read(ums_dev->dev_num, -			start + ums_dev->offset, blkcnt, buf) != blkcnt) -		return -1; - -	return 0; -} - -static int ums_write_sector(struct ums_device *ums_dev, -			    ulong start, lbaint_t blkcnt, const void *buf) -{ -	if (ums_dev->mmc->block_dev.block_write(ums_dev->dev_num, -			start + ums_dev->offset, blkcnt, buf) != blkcnt) -		return -1; - -	return 0; -} - -static void ums_get_capacity(struct ums_device *ums_dev, -			     long long int *capacity) -{ -	long long int tmp_capacity; - -	tmp_capacity = (long long int) ((ums_dev->offset + ums_dev->part_size) -					* SECTOR_SIZE); -	*capacity = ums_dev->mmc->capacity - tmp_capacity; -} - -static struct ums_board_info ums_board = { -	.read_sector = ums_read_sector, -	.write_sector = ums_write_sector, -	.get_capacity = ums_get_capacity, -	.name = "TRATS UMS disk", -	.ums_dev = { -		.mmc = NULL, -		.dev_num = 0, -		.offset = 0, -		.part_size = 0. -	}, -}; - -struct ums_board_info *board_ums_init(unsigned int dev_num, unsigned int offset, -				      unsigned int part_size) -{ -	struct mmc *mmc; - -	mmc = find_mmc_device(dev_num); -	if (!mmc) -		return NULL; - -	ums_board.ums_dev.mmc = mmc; -	ums_board.ums_dev.dev_num = dev_num; -	ums_board.ums_dev.offset = offset; -	ums_board.ums_dev.part_size = part_size; - -	return &ums_board; -} -#endif diff --git a/common/cmd_usb_mass_storage.c b/common/cmd_usb_mass_storage.c index f583cafa3..99487f4d0 100644 --- a/common/cmd_usb_mass_storage.c +++ b/common/cmd_usb_mass_storage.c @@ -5,6 +5,7 @@   * SPDX-License-Identifier:	GPL-2.0+   */ +#include <errno.h>  #include <common.h>  #include <command.h>  #include <g_dnl.h> @@ -20,55 +21,49 @@ int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag,  	const char *usb_controller = argv[1];  	const char *mmc_devstring  = argv[2]; -	unsigned int dev_num = (unsigned int)(simple_strtoul(mmc_devstring, -				NULL, 0)); -	if (dev_num) { -		error("Set eMMC device to 0! - e.g. ums 0"); -		goto fail; -	} +	unsigned int dev_num = simple_strtoul(mmc_devstring, NULL, 0); + +	struct ums *ums = ums_init(dev_num); +	if (!ums) +		return CMD_RET_FAILURE;  	unsigned int controller_index = (unsigned int)(simple_strtoul(  					usb_controller,	NULL, 0));  	if (board_usb_init(controller_index, USB_INIT_DEVICE)) {  		error("Couldn't init USB controller."); -		goto fail; -	} - -	struct ums_board_info *ums_info = board_ums_init(dev_num, 0, 0); -	if (!ums_info) { -		error("MMC: %d -> NOT available", dev_num); -		goto fail; +		return CMD_RET_FAILURE;  	} -	int rc = fsg_init(ums_info); +	int rc = fsg_init(ums);  	if (rc) {  		error("fsg_init failed"); -		goto fail; +		return CMD_RET_FAILURE;  	}  	g_dnl_register("ums");  	while (1) { -		/* Handle control-c and timeouts */ -		if (ctrlc()) { -			error("The remote end did not respond in time."); -			goto exit; -		} -  		usb_gadget_handle_interrupts(); -		/* Check if USB cable has been detached */ -		if (fsg_main_thread(NULL) == EIO) + +		rc = fsg_main_thread(NULL); +		if (rc) { +			/* Check I/O error */ +			if (rc == -EIO) +				printf("\rCheck USB cable connection\n"); + +			/* Check CTRL+C */ +			if (rc == -EPIPE) +				printf("\rCTRL+C - Operation aborted\n"); +  			goto exit; +		}  	}  exit:  	g_dnl_unregister(); -	return 0; - -fail: -	return -1; +	return CMD_RET_SUCCESS;  }  U_BOOT_CMD(ums, CONFIG_SYS_MAXARGS, 1, do_usb_mass_storage,  	"Use the UMS [User Mass Storage]", -	"<USB_controller> <mmc_dev>" +	"ums <USB_controller> <mmc_dev>  e.g. ums 0 0"  ); diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 4a8804e4b..1eb92e541 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -229,6 +229,7 @@ static int dfu_read_buffer_fill(struct dfu_entity *dfu, void *buf, int size)  			dfu->crc = crc32(dfu->crc, buf, chunk);  			dfu->i_buf += chunk;  			dfu->b_left -= chunk; +			dfu->r_left -= chunk;  			size -= chunk;  			buf += chunk;  			readn += chunk; @@ -287,7 +288,7 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)  		dfu->offset = 0;  		dfu->i_buf_end = dfu_get_buf() + dfu_buf_size;  		dfu->i_buf = dfu->i_buf_start; -		dfu->b_left = 0; +		dfu->b_left = min(dfu_buf_size, dfu->r_left);  		dfu->bad_skip = 0; diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c index edbf5a97b..2d07097e8 100644 --- a/drivers/dfu/dfu_nand.c +++ b/drivers/dfu/dfu_nand.c @@ -121,6 +121,7 @@ static int dfu_read_medium_nand(struct dfu_entity *dfu, u64 offset, void *buf,  	switch (dfu->layout) {  	case DFU_RAW_ADDR: +		*len = dfu->data.nand.size;  		ret = nand_block_read(dfu, offset, buf, len);  		break;  	default: diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 6ecdea3e1..b1fe8bd3a 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -243,6 +243,7 @@  #include <config.h>  #include <malloc.h>  #include <common.h> +#include <usb.h>  #include <linux/err.h>  #include <linux/usb/ch9.h> @@ -441,7 +442,7 @@ static void set_bulk_out_req_length(struct fsg_common *common,  /*-------------------------------------------------------------------------*/ -struct ums_board_info			*ums_info; +struct ums *ums;  struct fsg_common *the_fsg_common;  static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) @@ -675,6 +676,18 @@ static int sleep_thread(struct fsg_common *common)  			k++;  		} +		if (k == 10) { +			/* Handle CTRL+C */ +			if (ctrlc()) +				return -EPIPE; +#ifdef CONFIG_USB_CABLE_CHECK +			/* Check cable connection */ +			if (!usb_cable_connected()) +				return -EIO; +#endif +			k = 0; +		} +  		usb_gadget_handle_interrupts();  	}  	common->thread_wakeup_needed = 0; @@ -757,14 +770,14 @@ static int do_read(struct fsg_common *common)  		}  		/* Perform the read */ -		nread = 0; -		rc = ums_info->read_sector(&(ums_info->ums_dev), -					   file_offset / SECTOR_SIZE, -					   amount / SECTOR_SIZE, -					   (char __user *)bh->buf); -		if (rc) +		rc = ums->read_sector(ums, +				      file_offset / SECTOR_SIZE, +				      amount / SECTOR_SIZE, +				      (char __user *)bh->buf); +		if (!rc)  			return -EIO; -		nread = amount; + +		nread = rc * SECTOR_SIZE;  		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,  				(unsigned long long) file_offset, @@ -931,13 +944,13 @@ static int do_write(struct fsg_common *common)  			amount = bh->outreq->actual;  			/* Perform the write */ -			rc = ums_info->write_sector(&(ums_info->ums_dev), +			rc = ums->write_sector(ums,  					       file_offset / SECTOR_SIZE,  					       amount / SECTOR_SIZE,  					       (char __user *)bh->buf); -			if (rc) +			if (!rc)  				return -EIO; -			nwritten = amount; +			nwritten = rc * SECTOR_SIZE;  			VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,  					(unsigned long long) file_offset, @@ -959,6 +972,8 @@ static int do_write(struct fsg_common *common)  			/* If an error occurred, report it and its position */  			if (nwritten < amount) { +				printf("nwritten:%d amount:%d\n", nwritten, +				       amount);  				curlun->sense_data = SS_WRITE_ERROR;  				curlun->info_valid = 1;  				break; @@ -1045,14 +1060,13 @@ static int do_verify(struct fsg_common *common)  		}  		/* Perform the read */ -		nread = 0; -		rc = ums_info->read_sector(&(ums_info->ums_dev), -					   file_offset / SECTOR_SIZE, -					   amount / SECTOR_SIZE, -					   (char __user *)bh->buf); -		if (rc) +		rc = ums->read_sector(ums, +				      file_offset / SECTOR_SIZE, +				      amount / SECTOR_SIZE, +				      (char __user *)bh->buf); +		if (!rc)  			return -EIO; -		nread = amount; +		nread = rc * SECTOR_SIZE;  		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,  				(unsigned long long) file_offset, @@ -1100,7 +1114,7 @@ static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh)  	buf[4] = 31;		/* Additional length */  				/* No special options */  	sprintf((char *) (buf + 8), "%-8s%-16s%04x", (char*) vendor_id , -			ums_info->name, (u16) 0xffff); +			ums->name, (u16) 0xffff);  	return 36;  } @@ -2386,6 +2400,7 @@ static void handle_exception(struct fsg_common *common)  int fsg_main_thread(void *common_)  { +	int ret;  	struct fsg_common	*common = the_fsg_common;  	/* The main loop */  	do { @@ -2395,12 +2410,16 @@ int fsg_main_thread(void *common_)  		}  		if (!common->running) { -			sleep_thread(common); +			ret = sleep_thread(common); +			if (ret) +				return ret; +  			continue;  		} -		if (get_next_command(common)) -			continue; +		ret = get_next_command(common); +		if (ret) +			return ret;  		if (!exception_in_progress(common))  			common->state = FSG_STATE_DATA_PHASE; @@ -2753,9 +2772,9 @@ int fsg_add(struct usb_configuration *c)  	return fsg_bind_config(c->cdev, c, fsg_common);  } -int fsg_init(struct ums_board_info *ums) +int fsg_init(struct ums *ums_dev)  { -	ums_info = ums; +	ums = ums_dev;  	return 0;  } diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c index 43f413aab..8dc3d9f8a 100644 --- a/drivers/usb/gadget/g_dnl.c +++ b/drivers/usb/gadget/g_dnl.c @@ -33,6 +33,9 @@  #define STRING_PRODUCT 2  /* Index of String Descriptor describing this configuration */  #define STRING_USBDOWN 2 +/* Index of String serial */ +#define STRING_SERIAL  3 +#define MAX_STRING_SERIAL	32  /* Number of supported configurations */  #define CONFIGURATION_NUMBER 1 @@ -40,8 +43,16 @@  static const char shortname[] = "usb_dnl_";  static const char product[] = "USB download gadget"; +static char g_dnl_serial[MAX_STRING_SERIAL];  static const char manufacturer[] = CONFIG_G_DNL_MANUFACTURER; +void g_dnl_set_serialnumber(char *s) +{ +	memset(g_dnl_serial, 0, MAX_STRING_SERIAL); +	if (strlen(s) < MAX_STRING_SERIAL) +		strncpy(g_dnl_serial, s, strlen(s)); +} +  static struct usb_device_descriptor device_desc = {  	.bLength = sizeof device_desc,  	.bDescriptorType = USB_DT_DEVICE, @@ -53,6 +64,7 @@ static struct usb_device_descriptor device_desc = {  	.idVendor = __constant_cpu_to_le16(CONFIG_G_DNL_VENDOR_NUM),  	.idProduct = __constant_cpu_to_le16(CONFIG_G_DNL_PRODUCT_NUM),  	.iProduct = STRING_PRODUCT, +	.iSerialNumber = STRING_SERIAL,  	.bNumConfigurations = 1,  }; @@ -63,6 +75,7 @@ static struct usb_device_descriptor device_desc = {  static struct usb_string g_dnl_string_defs[] = {  	{.s = manufacturer},  	{.s = product}, +	{.s = g_dnl_serial},  	{ }		/* end of list */  }; @@ -156,6 +169,13 @@ static int g_dnl_bind(struct usb_composite_dev *cdev)  	g_dnl_string_defs[1].id = id;  	device_desc.iProduct = id; +	id = usb_string_id(cdev); +	if (id < 0) +		return id; + +	g_dnl_string_defs[2].id = id; +	device_desc.iSerialNumber = id; +  	g_dnl_bind_fixup(&device_desc, cdev->driver->name);  	ret = g_dnl_config_register(cdev);  	if (ret) diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index 866e7c7b8..02803df23 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -275,7 +275,6 @@ struct rw_semaphore { int i; };  #define ETOOSMALL	525  #include <usb_mass_storage.h> -extern struct ums_board_info		*ums_info;  /*-------------------------------------------------------------------------*/ @@ -573,36 +572,16 @@ static struct usb_gadget_strings	fsg_stringtab = {  static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)  {  	int				ro; -	int				rc = -EINVAL; -	loff_t				size; -	loff_t				num_sectors; -	loff_t				min_sectors;  	/* R/W if we can, R/O if we must */  	ro = curlun->initially_ro; -	ums_info->get_capacity(&(ums_info->ums_dev), &size); -	if (size < 0) { -		printf("unable to find file size: %s\n", filename); -		rc = (int) size; -		goto out; -	} -	num_sectors = size >> 9;	/* File size in 512-byte blocks */ -	min_sectors = 1; -	if (num_sectors < min_sectors) { -		printf("file too small: %s\n", filename); -		rc = -ETOOSMALL; -		goto out; -	} -  	curlun->ro = ro; -	curlun->file_length = size; -	curlun->num_sectors = num_sectors; +	curlun->file_length = ums->num_sectors << 9; +	curlun->num_sectors = ums->num_sectors;  	debug("open backing file: %s\n", filename); -	rc = 0; -out: -	return rc; +	return 0;  }  static void fsg_lun_close(struct fsg_lun *curlun) diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 4ed07da84..219d18232 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1548,7 +1548,7 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,  	}  	dev->status = stat; -	dev->act_len = transfer_len; +	dev->act_len = urb->actual_length;  #ifdef DEBUG  	pkt_print(urb, dev, pipe, buffer, transfer_len, diff --git a/include/configs/trats.h b/include/configs/trats.h index 6ed331326..3d080c4d1 100644 --- a/include/configs/trats.h +++ b/include/configs/trats.h @@ -321,9 +321,7 @@  #define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE ((500 * 120 * 4) + (1 << 12))  #define CONFIG_CMD_USB_MASS_STORAGE -#if defined(CONFIG_CMD_USB_MASS_STORAGE)  #define CONFIG_USB_GADGET_MASS_STORAGE -#endif  /* Pass open firmware flat tree */  #define CONFIG_OF_LIBFDT    1 diff --git a/include/g_dnl.h b/include/g_dnl.h index de669fb85..8f813c21e 100644 --- a/include/g_dnl.h +++ b/include/g_dnl.h @@ -13,5 +13,6 @@  int g_dnl_bind_fixup(struct usb_device_descriptor *, const char *);  int g_dnl_register(const char *s);  void g_dnl_unregister(void); +void g_dnl_set_serialnumber(char *);  #endif /* __G_DOWNLOAD_H_ */ diff --git a/include/usb.h b/include/usb.h index d9fedeeff..736730e89 100644 --- a/include/usb.h +++ b/include/usb.h @@ -197,6 +197,16 @@ int board_usb_init(int index, enum usb_init_type init);   */  int board_usb_cleanup(int index, enum usb_init_type init); +/* + * If CONFIG_USB_CABLE_CHECK is set then this function + * should be defined in board file. + * + * @return 1 if cable is connected and 0 otherwise. + */ +#ifdef CONFIG_USB_CABLE_CHECK +int usb_cable_connected(void); +#endif +  #ifdef CONFIG_USB_STORAGE  #define USB_MAX_STOR_DEV 5 diff --git a/include/usb_mass_storage.h b/include/usb_mass_storage.h index 13f535ce2..9df3adcf2 100644 --- a/include/usb_mass_storage.h +++ b/include/usb_mass_storage.h @@ -9,32 +9,33 @@  #define __USB_MASS_STORAGE_H__  #define SECTOR_SIZE		0x200 -  #include <mmc.h>  #include <linux/usb/composite.h> -struct ums_device { -	struct mmc *mmc; -	int dev_num; -	int offset; -	int part_size; -}; +#ifndef UMS_START_SECTOR +#define UMS_START_SECTOR	0 +#endif -struct ums_board_info { -	int (*read_sector)(struct ums_device *ums_dev, +#ifndef UMS_NUM_SECTORS +#define UMS_NUM_SECTORS		0 +#endif + +struct ums { +	int (*read_sector)(struct ums *ums_dev,  			   ulong start, lbaint_t blkcnt, void *buf); -	int (*write_sector)(struct ums_device *ums_dev, +	int (*write_sector)(struct ums *ums_dev,  			    ulong start, lbaint_t blkcnt, const void *buf); -	void (*get_capacity)(struct ums_device *ums_dev, -			     long long int *capacity); +	unsigned int start_sector; +	unsigned int num_sectors;  	const char *name; -	struct ums_device ums_dev; +	struct mmc *mmc;  }; -int fsg_init(struct ums_board_info *); +extern struct ums *ums; + +int fsg_init(struct ums *);  void fsg_cleanup(void); -struct ums_board_info *board_ums_init(unsigned int, unsigned int, -				      unsigned int); +struct ums *ums_init(unsigned int);  int fsg_main_thread(void *);  #ifdef CONFIG_USB_GADGET_MASS_STORAGE |