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

📄 myudisk.c

📁 linux下的U盘驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (cs->sc_data_direction == SCSI_DATA_WRITE) {		doDefault = 1;	}	else		switch (lengths[cs->cmnd[0]]) {			case 'L':				len = cs->cmnd[4];				break;			case 'M':				len = cs->cmnd[8];				break;			case '0':			case '1':			case '2':			case '3':			case '4':			case '5':			case '6':			case '7':			case '8':			case '9':				len = lengths[cs->cmnd[0]]-'0';				break;			case 'G':				len = (((unsigned int)cs->cmnd[3])<<8) |					cs->cmnd[4];				break;			case 'H':				len = (((unsigned int)cs->cmnd[7])<<8) |					cs->cmnd[8];				break;			case 'I':				len = (((unsigned int)cs->cmnd[8])<<8) |					cs->cmnd[9];				break;			case 'R':				len = (((unsigned int)cs->cmnd[2])<<16) |					(((unsigned int)cs->cmnd[3])<<8) |					cs->cmnd[4];				break;			case 'S':				len = (((unsigned int)cs->cmnd[3])<<16) |					(((unsigned int)cs->cmnd[4])<<8) |					cs->cmnd[5];				break;			case 'T':				len = (((unsigned int)cs->cmnd[6])<<16) |					(((unsigned int)cs->cmnd[7])<<8) |					cs->cmnd[8];				break;			case 'U':				len = (((unsigned int)cs->cmnd[7])<<16) |					(((unsigned int)cs->cmnd[8])<<8) |					cs->cmnd[9];				break;			case 'C':				len = (((unsigned int)cs->cmnd[2])<<24) |					(((unsigned int)cs->cmnd[3])<<16) |					(((unsigned int)cs->cmnd[4])<<8) |					cs->cmnd[5];				break;			case 'D':				len = (((unsigned int)cs->cmnd[6])<<24) |					(((unsigned int)cs->cmnd[7])<<16) |					(((unsigned int)cs->cmnd[8])<<8) |					cs->cmnd[9];				break;			case 'V':				len = 20;				break;			case 'W':				len = 24;				break;			case 'B':				/* Use buffer size due to different block sizes */				doDefault = 1;				break;			case 'X':				dbg("Error: UNSUPPORTED COMMAND %02X\n",						cs->cmnd[0]);				doDefault = 1;				break;			case 'Z':				/* Use buffer size due to mode dependence */				doDefault = 1;				break;			default:				dbg("Error: COMMAND %02X out of range or table inconsistent (%c).\n",					cs->cmnd[0], lengths[cs->cmnd[0]] );				doDefault = 1;		}	   	if ( doDefault == 1 ) {		len = cs->data_payload_size;	}		dbg("doDefault %d, data length %u", doDefault, len);	return len;}//////////////////////////////////////////////////////////////////////////////////////////////reset/* This issues a Bulk-only Reset to the device in question, including * clearing the subsequent endpoint halts that may occur. */int myudisk_Bulk_reset(struct usb_device *udev, struct usb_interface *interface,                        __u8 bulk_in_endpointAddr, __u8 bulk_out_endpointAddr){	int result;	dbg("Bulk reset requested\n");	/* if the device was removed, then we're already reset */	if (!udev)		return SUCCESS;	result = usb_control_msg(udev, 				 usb_sndctrlpipe(udev,0), 				 MU_BULK_RESET_REQUEST, 				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,				 0, 				 interface->altsetting[0].bInterfaceNumber, 				 NULL, 0, HZ*5);	if (result < 0) {		dbg("Bulk soft reset failed %d\n", result);		return FAILED;	}	/* long wait for reset */	set_current_state(TASK_UNINTERRUPTIBLE);	schedule_timeout(HZ*6);	set_current_state(TASK_RUNNING);	usb_clear_halt(udev, usb_rcvbulkpipe(udev, bulk_in_endpointAddr));	usb_clear_halt(udev, usb_sndbulkpipe(udev, bulk_out_endpointAddr));	dbg("Bulk soft reset completed\n");	return SUCCESS;}////////////////////////////////////////////////////////////////////////////////////////////////////int myudisk_Bulk_transport(struct usb_device *udev, struct usb_interface *interface,                           struct cmnd_struct *cs,                            unsigned char *bulk_buffer, int bulk_size,                           __u8 bulk_in_endpointAddr, __u8 bulk_out_endpointAddr){	struct bulk_cb_wrap *bcb;	struct bulk_cs_wrap *bcs;	int result;	int pipe;	int partial;	char *buf;	unsigned int transfer_amount;	int ret = MYUDISK_TRANSPORT_ERROR;	bcb = kmalloc(sizeof *bcb, in_interrupt() ? GFP_ATOMIC : GFP_NOIO);	if (!bcb) {		return MYUDISK_TRANSPORT_ERROR;	}	bcs = kmalloc(sizeof *bcs, in_interrupt() ? GFP_ATOMIC : GFP_NOIO);	if (!bcs) {		kfree(bcb);		return MYUDISK_TRANSPORT_ERROR;	}	/* set up the command wrapper */	bcb->Signature = cpu_to_le32(MU_BULK_CB_SIGN);	transfer_amount = myudisk_transfer_length(cs);	bcb->DataTransferLength = cpu_to_le32(transfer_amount);	bcb->Flags = cs->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;	bcb->Tag = ++(cs->tag);	bcb->Lun = cs->cmnd[1] >> 5;	bcb->Length = cs->cmd_len;	/* construct the pipe handle */	pipe = usb_sndbulkpipe(udev, bulk_out_endpointAddr);	/* copy the command payload */	memset(bcb->CDB, 0, sizeof(bcb->CDB));	memcpy(bcb->CDB, cs->cmnd, bcb->Length);	/* send it to out endpoint */	myudisk_debug_data ("command to send", MU_BULK_CB_WRAP_LEN, (unsigned char *)bcb);	dbg("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d",		  le32_to_cpu(bcb->Signature), bcb->Tag,		  (bcb->Lun >> 4), (bcb->Lun & 0x0F), 		  bcb->DataTransferLength, bcb->Flags, bcb->Length);	result = usb_bulk_msg(udev, 			      pipe, 			      bcb, MU_BULK_CB_WRAP_LEN,			      &partial, MYUDISK_TIMEOUT);	dbg("Bulk command transfer result=%d, xferred %d/%d", 	    result, partial, MU_BULK_CB_WRAP_LEN);	/* if the command was aborted, indicate that */	if (result == -ECONNRESET) {		ret = MYUDISK_TRANSPORT_ABORTED;		goto out;	}	/* if we stall, we need to clear it before we go on */	if (result == -EPIPE) {		dbg("clearing endpoint halt for pipe 0x%x", pipe);		result = usb_clear_halt(udev, pipe);		/* if the command was aborted, indicate that */		if (result == -ECONNRESET) {			ret = MYUDISK_TRANSPORT_ABORTED;			goto out;		}		result = -EPIPE;	} else if (result) {		/* unknown error -- we've got a problem */		ret = MYUDISK_TRANSPORT_ERROR;		goto out;	}	dbg("----cmnd end\n");	/* if the command transfered well, then we go to the data stage */	if (result == 0) {		/* send/receive data payload, if there is any */		if (bcb->DataTransferLength) {			/* calculate the appropriate pipe and buffer information */			if (cs->sc_data_direction == SCSI_DATA_READ) {				pipe = usb_rcvbulkpipe(udev, bulk_in_endpointAddr);				buf = bulk_buffer;				if (transfer_amount > bulk_size) {					dbg("illegal DataTransferLength!");					transfer_amount = bulk_size;				}			} else {				pipe = usb_sndbulkpipe(udev, bulk_out_endpointAddr);				buf = bulk_buffer;				if (transfer_amount > bulk_size) {					dbg("illegal DataTransferLength!");					transfer_amount = bulk_size;				}			}					/* transfer the data */			dbg("xfer %d bytes data", transfer_amount);			result = usb_bulk_msg(udev, 					pipe, 					buf, transfer_amount,					&partial, MYUDISK_TIMEOUT);			cs->data_payload_actualSize = partial;			dbg("Bulk data transfer result: %d, xferred %d/%d",				  result, partial, transfer_amount);//			myudisk_debug_data ("data transfered", partial, buf);					/* if we stall, we need to clear it before we go on */			if (result == -EPIPE) {				dbg("clearing endpoint halt for pipe 0x%x", pipe);				usb_clear_halt(udev, pipe);			}			/* if it was aborted, we need to indicate that */			if (result) {				ret = MYUDISK_TRANSPORT_ABORTED;				goto out;			}		}	}	dbg("----data end\n");		/* See flow chart on pg 15 of the Bulk Only Transport spec for	 * an explanation of how this code works.	 */	/* construct the pipe handle */	pipe = usb_rcvbulkpipe(udev, bulk_in_endpointAddr);	/* get CSW for device status */	dbg("Attempting to get CSW...");	result = usb_bulk_msg(udev, 			pipe, 			bcs, MU_BULK_CS_WRAP_LEN, 			&partial, MYUDISK_TIMEOUT);	dbg("Bulk status transfer result = %d, xferred %d/%d", result, partial, MU_BULK_CS_WRAP_LEN);	/* if the command was aborted, indicate that */	if (result == -ECONNRESET) {		ret = MYUDISK_TRANSPORT_ABORTED;		goto out;	}	/* did the attempt to read the CSW fail? */	if (result == -EPIPE) {		dbg("clearing endpoint halt for pipe 0x%x", pipe);		result = usb_clear_halt(udev, pipe);		/* if the command was aborted, indicate that */		if (result == -ECONNRESET) {			ret = MYUDISK_TRANSPORT_ABORTED;			goto out;		}		/* get the status again */		dbg("Attempting to get CSW (2nd try)...");		result = usb_bulk_msg(udev, 				pipe,				bcs, MU_BULK_CS_WRAP_LEN, 				&partial, MYUDISK_TIMEOUT);		/* if the command was aborted, indicate that */		if (result == -ECONNRESET) {			ret = MYUDISK_TRANSPORT_ABORTED;			goto out;		}		/* if it fails again, we need a reset and return an error*/		if (result == -EPIPE) {			dbg("clearing halt for pipe 0x%x", pipe);			result = usb_clear_halt(udev, pipe);			/* if the command was aborted, indicate that */			if (result == -ECONNRESET) {				ret = MYUDISK_TRANSPORT_ABORTED;			} else {				ret = MYUDISK_TRANSPORT_ERROR;			}			goto out;		}	}	/* if we still have a failure at this point, we're in trouble */	if (result) {		ret = MYUDISK_TRANSPORT_ERROR;		goto out;	}	/* check bulk status */	myudisk_debug_data ("status data recerived", partial, (unsigned char *)bcs);	dbg("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x",	    le32_to_cpu(bcs->Signature), bcs->Tag, bcs->Residue, bcs->Status);	if ((bcs->Signature != cpu_to_le32(MU_BULK_CS_SIGN) && bcs->Signature != cpu_to_le32(MU_BULK_CS_OLYMPUS_SIGN)) ||	    bcs->Tag != bcb->Tag || 	    bcs->Status > MU_BULK_STAT_PHASE || 	    partial != 13) {		dbg("Bulk logical error");		ret = MYUDISK_TRANSPORT_ERROR;		goto out;	}	/* based on the status code, we report good or bad */	switch (bcs->Status) {		case MU_BULK_STAT_OK:			/* command good -- note that data could be short */			ret = MYUDISK_TRANSPORT_GOOD;			goto out;		case MU_BULK_STAT_FAIL:			/* command failed */			ret = MYUDISK_TRANSPORT_FAILED;			goto out;		case MU_BULK_STAT_PHASE:			/* phase error -- note that a transport reset will be			 * invoked by the invoke_transport() function			 */			ret = MYUDISK_TRANSPORT_ERROR;			goto out;	}	/* we should never get here, but if we do, we're in trouble */	dbg("we should never get here."); out:	if (ret == MYUDISK_TRANSPORT_GOOD) {		dbg("transport indicates command was successful\n");	} else if (ret == MYUDISK_TRANSPORT_ABORTED || 	           ret == MYUDISK_TRANSPORT_ERROR) {		myudisk_Bulk_reset(udev, interface, 		                   bulk_in_endpointAddr, bulk_out_endpointAddr);		dbg("transport indicates command was aborted\n");	} 	kfree(bcb);	kfree(bcs);	return ret;}//////////////////////////////////////////////////////////////////////////////////////////////static void myudisk_disconnect(struct usb_device *udev, void *ptr){	struct my_udisk *dev;	int minor;	dev = (struct my_udisk *)ptr;		down (&minor_table_mutex);	down (&dev->sem);			minor = dev->minor;	/* remove our devfs node */	devfs_unregister(dev->devfs);	/* if the device is not opened, then we clean up right now */	if (!dev->open_count) {		up (&dev->sem);		myudisk_delete (dev);	} else {		dev->udev = NULL;		up (&dev->sem);	}	info("My UDisk #%d now disconnected", minor);	up (&minor_table_mutex);}/** *	my_udisk_init */static int __init my_udisk_init(void){	int result;	/* register this driver with the USB subsystem */	result = usb_register(&myudisk_driver);	if (result < 0) {		err("usb_register failed for the "__FILE__" driver. Error number %d",		    result);		return -1;	}	info(DRIVER_DESC " " DRIVER_VERSION);		/* 块大小必须是扇区大小的整数倍 */	/*if (myudisk_blocksize & ((1 << MYUDISK_SECTOR_BITS)-1)) {		dbg("Block size not a multiple of sector size\n");		return -EINVAL;	}*/		/* 分配存储空间 */	/*myudisk_storage = (char *) vmalloc(1024*myudisk_size);	if (myudisk_storage == NULL) {		dbg("Not enough memory. Try a smaller size.\n");		return -ENOMEM;	}*/	//memset(myudisk_storage, 0, 1024*myudisk_size);		/* 【重要】向系统注册块设备 */	result = register_blkdev(MAJOR_NR, DEVICE_NAME, &myudisk_fops);	if (result) {		dbg("couldn't register block device\n");		return result;	}		/* 在系统中注册块的大小、存储容量等参数 */	hardsect_size[MAJOR_NR] = &myudisk_hard;	blksize_size[MAJOR_NR] = &myudisk_soft;	blk_size[MAJOR_NR] = &myudisk_size;		/* 在系统中注册响应读写请求的函数 */	blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), &myudisk_request);	read_ahead[MAJOR_NR] = myudisk_readahead;			return 0;}/** *	my_udisk_exit */static void __exit my_udisk_exit(void){	/* deregister this driver with the USB subsystem */	usb_deregister(&myudisk_driver);	unregister_blkdev(MAJOR_NR, DEVICE_NAME);	invalidate_buffers(MKDEV(MAJOR_NR,0));	/* remove our request function */	blk_dev[MAJOR_NR].request_queue.request_fn = 0;		}module_init (my_udisk_init);module_exit (my_udisk_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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