⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uboot-dfu.patch

📁 Uboot常用的移植patches, 方便定制移植到s3c2440
💻 PATCH
📖 第 1 页 / 共 4 页
字号:
+				return rc;+			printf("Starting DFU DOWNLOAD to partition '%s'\n",+				ds->part->name);+		}++		size = ds->nand->erasesize;+		remain_len = ds->buf + size - ds->ptr;+		if (remain_len < len)+			actual_len = remain_len;++		memcpy(ds->ptr, urb->buffer, actual_len);+		ds->ptr += actual_len;++		/* check partition end */+		if (ds->off + (ds->ptr - ds->buf) > ds->part->offset + ds->part->size) {+			printf("End of write exceeds partition end\n");+			dev->dfu_state = DFU_STATE_dfuERROR;+			dev->dfu_status = DFU_STATUS_errADDRESS;+			return RET_STALL;+		}++		if (ds->ptr >= ds->buf + size) {+			rc = erase_flash_verify_nand(urb, ds,+						     ds->nand->erasesize,+						     ds->nand->erasesize);+			if (rc)+				return rc;+			/* copy remainder of data into buffer */+			memcpy(ds->ptr, urb->buffer + actual_len, len - actual_len);+			ds->ptr += (len - actual_len);+		}+		break;+	}++	return RET_ZLP;+}++static int handle_upload(struct urb *urb, u_int16_t val, u_int16_t len, int first)+{+	struct usb_device_instance *dev = urb->device;+	struct dnload_state *ds = &_dnstate;+	unsigned int remain;+	int rc;++	debug("upload(val=0x%02x, len=%u, first=%u) ", val, len, first);++	if (len > CONFIG_USBD_DFU_XFER_SIZE) {+		/* Too big */+		dev->dfu_state = DFU_STATE_dfuERROR;+		dev->dfu_status = DFU_STATUS_errADDRESS;+		//udc_ep0_send_stall();+		debug("Error: Transfer size > CONFIG_USBD_DFU_XFER_SIZE ");+		return -EINVAL;+	}++	switch (dev->alternate) {+	case 0:+		if (first) {+			printf("Starting DFU Upload of RAM (0x%08p)\n",+				LOAD_ADDR);+			ds->ptr = ds->buf;+		}++		/* FIXME: end at some more dynamic point */+		if (ds->ptr + len > LOAD_ADDR + 0x200000)+			len = (LOAD_ADDR + 0x200000) - ds->ptr;++		urb->buffer = ds->ptr;+		urb->actual_length = len;+		ds->ptr += len;+		break;+	default:+		if (first) {+			rc = initialize_ds_nand(dev, ds);+			if (rc)+				return -EINVAL;+			printf("Starting DFU Upload of partition '%s'\n",+				ds->part->name);+			rc = read_next_nand(urb, ds);+			if (rc)+				return -EINVAL;+		}++		if (len > ds->nand->erasesize) {+			printf("We don't support transfers bigger than %u\n",+				ds->nand->erasesize);+			len = ds->nand->erasesize;+		}++		remain = ds->nand->erasesize - (ds->ptr - ds->buf);+		if (len < remain)+			remain = len;++		debug("copying %u bytes ", remain);+		urb->buffer = ds->ptr;+		ds->ptr += remain;+		urb->actual_length = remain;++		if (ds->ptr >= ds->buf + ds->nand->erasesize &&+		    ds->off < ds->part->offset + ds->part->size) {+			rc = read_next_nand(urb, ds);+			if (rc)+				return -EINVAL;+			if (len > remain) {+				debug("copying another %u bytes ", len - remain);+				memcpy(urb->buffer + remain, ds->ptr, len - remain);+				ds->ptr += (len - remain);+				urb->actual_length += (len - remain);+			}+		}+		break;+	}++	debug("returning len=%u\n", len);+	return len;+}++static void handle_getstatus(struct urb *urb, int max)+{+	struct usb_device_instance *dev = urb->device;+	struct dfu_status *dstat = (struct dfu_status *) urb->buffer;++	debug("getstatus ");++	if (!urb->buffer || urb->buffer_length < sizeof(*dstat)) {+		debug("invalid urb! ");+		return;+	}++	switch (dev->dfu_state) {+	case DFU_STATE_dfuDNLOAD_SYNC:+	case DFU_STATE_dfuDNBUSY:+#if 0+		if (fsr & AT91C_MC_PROGE) {+			debug("errPROG ");+			dev->dfu_status = DFU_STATUS_errPROG;+			dev->dfu_state = DFU_STATE_dfuERROR;+		} else if (fsr & AT91C_MC_LOCKE) {+			debug("errWRITE ");+			dev->dfu_status = DFU_STATUS_errWRITE;+			dev->dfu_state = DFU_STATE_dfuERROR;+		} else if (fsr & AT91C_MC_FRDY) {+#endif+			debug("DNLOAD_IDLE ");+			dev->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;+#if 0+		} else {+			debug("DNBUSY ");+			dev->dfu_state = DFU_STATE_dfuDNBUSY;+		}+#endif+		break;+	case DFU_STATE_dfuMANIFEST_SYNC:+		break;+	default:+		//return;+		break;+	}++	/* send status response */+	dstat->bStatus = dev->dfu_status;+	dstat->bState = dev->dfu_state;+	dstat->iString = 0;+	/* FIXME: set dstat->bwPollTimeout */+	urb->actual_length = MIN(sizeof(*dstat), max);++	/* we don't need to explicitly send data here, will+	 * be done by the original caller! */+}++static void handle_getstate(struct urb *urb, int max)+{+	debug("getstate ");++	if (!urb->buffer || urb->buffer_length < sizeof(u_int8_t)) {+		debug("invalid urb! ");+		return;+	}++	urb->buffer[0] = urb->device->dfu_state & 0xff;+	urb->actual_length = sizeof(u_int8_t);+}++#ifndef CONFIG_USBD_PRODUCTID_DFU+#define CONFIG_USBD_PRODUCTID_DFU CONFIG_USBD_PRODUCTID_CDCACM+#endif++static const struct usb_device_descriptor dfu_dev_descriptor = {+	.bLength		= USB_DT_DEVICE_SIZE,+	.bDescriptorType	= USB_DT_DEVICE,+	.bcdUSB			= 0x0100,+	.bDeviceClass		= 0x00,+	.bDeviceSubClass	= 0x00,+	.bDeviceProtocol	= 0x00,+	.bMaxPacketSize0	= EP0_MAX_PACKET_SIZE,+	.idVendor		= CONFIG_USBD_VENDORID,+	.idProduct		= CONFIG_USBD_PRODUCTID_DFU,+	.bcdDevice		= 0x0000,+	.iManufacturer		= DFU_STR_MANUFACTURER,+	.iProduct		= DFU_STR_PRODUCT,+	.iSerialNumber		= DFU_STR_SERIAL,+	.bNumConfigurations	= 0x01,+};++static struct _dfu_desc dfu_cfg_descriptor = {+	.ucfg = {+		.bLength		= USB_DT_CONFIG_SIZE,+		.bDescriptorType	= USB_DT_CONFIG,+		.wTotalLength		= USB_DT_CONFIG_SIZE ++					  DFU_NUM_ALTERNATES * USB_DT_INTERFACE_SIZE ++					  USB_DT_DFU_SIZE,+		.bNumInterfaces		= 1,+		.bConfigurationValue	= 1,+		.iConfiguration		= DFU_STR_CONFIG,+		.bmAttributes		= BMATTRIBUTE_RESERVED,+		.bMaxPower		= 50,+	},+	.func_dfu = DFU_FUNC_DESC,+};++int dfu_ep0_handler(struct urb *urb)+{+	int rc, ret = RET_NOTHING;+	u_int8_t req = urb->device_request.bRequest;+	u_int16_t val = urb->device_request.wValue;+	u_int16_t len = urb->device_request.wLength;+	struct usb_device_instance *dev = urb->device;++	debug("dfu_ep0(req=0x%x, val=0x%x, len=%u) old_state = %u ",+		req, val, len, dev->dfu_state);++	switch (dev->dfu_state) {+	case DFU_STATE_appIDLE:+		switch (req) {+		case USB_REQ_DFU_GETSTATUS:+			handle_getstatus(urb, len);+			break;+		case USB_REQ_DFU_GETSTATE:+			handle_getstate(urb, len);+			break;+		case USB_REQ_DFU_DETACH:+			dev->dfu_state = DFU_STATE_appDETACH;+			ret = RET_ZLP;+			goto out;+			break;+		default:+			ret = RET_STALL;+		}+		break;+	case DFU_STATE_appDETACH:+		switch (req) {+		case USB_REQ_DFU_GETSTATUS:+			handle_getstatus(urb, len);+			break;+		case USB_REQ_DFU_GETSTATE:+			handle_getstate(urb, len);+			break;+		default:+			dev->dfu_state = DFU_STATE_appIDLE;+			ret = RET_STALL;+			goto out;+			break;+		}+		/* FIXME: implement timer to return to appIDLE */+		break;+	case DFU_STATE_dfuIDLE:+		switch (req) {+		case USB_REQ_DFU_DNLOAD:+			if (len == 0) {+				dev->dfu_state = DFU_STATE_dfuERROR;+				ret = RET_STALL;+				goto out;+			}+			dev->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;+			ret = handle_dnload(urb, val, len, 1);+			break;+		case USB_REQ_DFU_UPLOAD:+			dev->dfu_state = DFU_STATE_dfuUPLOAD_IDLE;+			handle_upload(urb, val, len, 1);+			break;+		case USB_REQ_DFU_ABORT:+			/* no zlp? */+			ret = RET_ZLP;+			break;+		case USB_REQ_DFU_GETSTATUS:+			handle_getstatus(urb, len);+			break;+		case USB_REQ_DFU_GETSTATE:+			handle_getstate(urb, len);+			break;+		case USB_REQ_DFU_DETACH:+			/* Proprietary extension: 'detach' from idle mode and+			 * get back to runtime mode in case of USB Reset.  As+			 * much as I dislike this, we just can't use every USB+			 * bus reset to switch back to runtime mode, since at+			 * least the Linux USB stack likes to send a number of resets+			 * in a row :( */+			dev->dfu_state = DFU_STATE_dfuMANIFEST_WAIT_RST;+			break;+		default:+			dev->dfu_state = DFU_STATE_dfuERROR;+			ret = RET_STALL;+			goto out;+			break;+		}+		break;+	case DFU_STATE_dfuDNLOAD_SYNC:+		switch (req) {+		case USB_REQ_DFU_GETSTATUS:+			handle_getstatus(urb, len);+			/* FIXME: state transition depending on block completeness */+			break;+		case USB_REQ_DFU_GETSTATE:+			handle_getstate(urb, len);+			break;+		default:+			dev->dfu_state = DFU_STATE_dfuERROR;+			ret = RET_STALL;+			goto out;+		}+		break;+	case DFU_STATE_dfuDNBUSY:+		switch (req) {+		case USB_REQ_DFU_GETSTATUS:+			/* FIXME: only accept getstatus if bwPollTimeout+			 * has elapsed */+			handle_getstatus(urb, len);+			break;+		default:+			dev->dfu_state = DFU_STATE_dfuERROR;+			ret = RET_STALL;+			goto out;+		}+		break;+	case DFU_STATE_dfuDNLOAD_IDLE:+		switch (req) {+		case USB_REQ_DFU_DNLOAD:+			dev->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;+			ret = handle_dnload(urb, val, len, 0);+			break;+		case USB_REQ_DFU_ABORT:+			dev->dfu_state = DFU_STATE_dfuIDLE;+			ret = RET_ZLP;+			break;+		case USB_REQ_DFU_GETSTATUS:+			handle_getstatus(urb, len);+			break;+		case USB_REQ_DFU_GETSTATE:+			handle_getstate(urb, len);+			break;+		default:+			dev->dfu_state = DFU_STATE_dfuERROR;+			ret = RET_STALL;+			break;+		}+		break;+	case DFU_STATE_dfuMANIFEST_SYNC:+		switch (req) {+		case USB_REQ_DFU_GETSTATUS:+			/* We're MainfestationTolerant */+			dev->dfu_state = DFU_STATE_dfuIDLE;+			handle_getstatus(urb, len);+			break;+		case USB_REQ_DFU_GETSTATE:+			handle_getstate(urb, len);+			break;+		default:+			dev->dfu_state = DFU_STATE_dfuERROR;+			ret = RET_STALL;+			break;+		}+		break;+	case DFU_STATE_dfuMANIFEST:+		/* we should never go here */+		dev->dfu_state = DFU_STATE_dfuERROR;+		ret = RET_STALL;+		break;+	case DFU_STATE_dfuMANIFEST_WAIT_RST:+		/* we should never go here */+		break;+	case DFU_STATE_dfuUPLOAD_IDLE:+		switch (req) {+		case USB_REQ_DFU_UPLOAD:+			/* state transition if less data then requested */+			rc = handle_upload(urb, val, len, 0);+			if (rc >= 0 && rc < len)+				dev->dfu_state = DFU_STATE_dfuIDLE;+			break;+		case USB_REQ_DFU_ABORT:+			dev->dfu_state = DFU_STATE_dfuIDLE;+			/* no zlp? */+			ret = RET_ZLP;+			break;+		case USB_REQ_DFU_GETSTATUS:+			handle_getstatus(urb, len);+			break;+		case USB_REQ_DFU_GETSTATE:+			handle_getstate(urb, len);+			break;+		default:+			dev->dfu_state = DFU_STATE_dfuERROR;+			ret = RET_STALL;+			break;+		}+		break;+	case DFU_STATE_dfuERROR:+		switch (req) {+		case USB_REQ_DFU_GETSTATUS:+			handle_getstatus(urb, len);+			break;+		case USB_REQ_DFU_GETSTATE:+			handle_getstate(urb, len);+			break;+		case USB_REQ_DFU_CLRSTATUS:+			dev->dfu_state = DFU_STATE_dfuIDLE;+			dev->dfu_status = DFU_STATUS_OK;+			/* no zlp? */+			ret = RET_ZLP;+			break;+		default:+			dev->dfu_state = DFU_STATE_dfuERROR;+			ret = RET_STALL;+			break;+		}+		break;+	default:+		return DFU_EP0_UNHANDLED;+		break;+	}++out:+	debug("new_state = %u, ret = %u\n", dev->dfu_state, ret);++	switch (ret) {+	case RET_ZLP:+		//udc_ep0_send_zlp();+		urb->actual_length = 0;+		return DFU_EP0_ZLP;+		break;+	case RET_STALL:+		//udc_ep0_send_stall();+		return DFU_EP0_STALL;+		break;+	case RET_NOTHING:+		break;+	}++	return DFU_EP0_DATA;+}++void str2wide (char *str, u16 * wide);+static struct usb_string_descriptor *create_usbstring(char *string)+{+	struct usb_string_descriptor *strdesc;+	int size = sizeof(*strdesc) + strlen(string)*2;++	if (size > 255)+		return NULL;++	strdesc = malloc(size);+	if (!strdesc)+		return NULL;++	strdesc->bLength = size;+	strdesc->bDescriptorType = USB_DT_STRING;+	str2wide(string, strdesc->wData);++	return strdesc;+}+++static void dfu_init_strings(struct usb_device_instance *dev)+{+	int i;+	struct usb_string_descriptor *strdesc;++	strdesc = create_usbstring(CONFIG_DFU_CFG_STR);+	usb_strings[DFU_STR_CONFIG] = strdesc;++	for (i = 0; i < DFU_NUM_ALTERNATES; i++) {+		if (i == 0) {+			strdesc = create_usbstring(CONFIG_DFU_ALT0_STR);+		} else {+			struct part_info *part = get_partition_nand(i-1);++			if (part)+				strdesc = create_usbstring(part->name);+			else+				strdesc =+				    create_usbstring("undefined partition");+		}+		if (!strdesc)+			continue;+		usb_strings[STR_COUNT+i+1] = strdesc;+	}+}+++#ifdef CONFIG_NAND_DYNPART++void dfu_update_strings(void)+{+	int i;++	if (!system_dfu_state) {+		printf("NASTY SURPRISE: system_dfu_state not set\n");+		return;+	}++	for (i = 1; i != DFU_NUM_ALTERNATES; i++) {+		struct part_info *part = get_partition_nand(i-1);+		struct usb_string_descriptor *strdesc, **slot;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -