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

📄 myudisk.c

📁 linux下的U盘驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* unlock the device */	up (&dev->sem);		/* return that we did not understand this ioctl call */	return -ENOTTY;  }/** *	myudisk_write_bulk_callback */static void myudisk_write_bulk_callback (struct urb *urb){	struct my_udisk *dev = (struct my_udisk *)urb->context;	dbg(" - minor %d", dev->minor);	if ((urb->status != -ENOENT) && 	    (urb->status != -ECONNRESET)) {		dbg(" - nonzero write bulk status received: %d",		    urb->status);		return;	}	return;}static int myudisk_request(request_queue_t *request_queue, int rw, struct buffer_head *sbh){	unsigned long  total;			//int *make_oops = NULL;    // CR: access to this pointer will cause Oops, for debug only.		//INIT_REQUEST;	//devno = DEVICE_NR(CURRENT->rq_dev);	/*if(devno>MAX_DEVICES);	{		printk("The device number is too larage!!!\n");		return 0;	}*/		//struct my_udisk *dev = CURRENT->rq_dev;	struct my_udisk *dev = minor_table[0];	int retval;	if(dev == NULL)		{			printk("Point to a unknown device !!! the dev is NULL\n");			return 0;		}	if (dev->udev == NULL) {		printk("the dev->udev is NULL!!!\n");		return -ENODEV;	}	dbg("%s sector rsector = %lu, blocknr = %lu\n",				rw == READ ? "read" : "write",				sbh->b_rsector,				sbh->b_blocknr);			//offset = sbh->b_rsector * myudisk_sectorsize;	total = (unsigned long)sbh->b_size;//计算需要访问的地址和大小	__u32 nLUN   = (__u32)(PARTION_offset + sbh->b_rsector);		/* access beyond end of the device */	if (total+nLUN> myudisk_size) {		dbg("Error: access beyond end of the device");		/* error in request  */		buffer_IO_error(sbh);		return 0;	}						//判断访问地址是否越界	dbg("offset = %lu, total = %lu\n", nLUN, total);	//printk("The request has to the read write function!!!\n");//singal of using for the debug!	struct cmnd_struct *com;	com = kmalloc (sizeof(struct cmnd_struct),GFP_KERNEL);	//////////////////////////////////////////////////////////////**********************/////////////////	if (rw == READ)	{	//如果是读操作,从虚拟盘的内存中复制数据到缓冲区中		//memcpy(bh_kmap(sbh), myudisk_storage+offset, total);		dbg("To the Read request!!!\n");			memset(dev->bulk_in_buffer,0,dev->bulk_in_size);			com->cmnd[0] = 0x28;			com->cmnd[1] = 0;			com->cmnd[2] = ((unsigned char)nLUN>>24) & 0xff;			com->cmnd[3] = ((unsigned char)nLUN>>16) & 0xff;			com->cmnd[4] = ((unsigned char)nLUN>>8) & 0xff;			com->cmnd[5] = ((unsigned char)nLUN) & 0xff;						com->cmnd[7] = (unsigned char)((total/myudisk_soft)>>8) & 0xff;			com->cmnd[8] = (unsigned char)(total/myudisk_soft) & 0xff;						com->cmd_len = 12;			com->data_payload_size = (unsigned long)sbh->b_size;			com->sc_data_direction = SCSI_DATA_READ;			com->tag = 0x12345678;;			myudisk_Bulk_transport(dev->udev,dev->interface, com, dev->bulk_in_buffer, dev->bulk_in_size, dev->bulk_in_endpointAddr, dev->bulk_out_endpointAddr);			memcpy(bh_kmap(sbh), dev->bulk_in_buffer,sbh->b_size);			memset(dev->bulk_in_buffer,0,dev->bulk_in_size);			dbg("usb_bulk_msg has successfully!!\n");			retval = (unsigned long)sbh->b_size;			}	else if (rw == WRITE) //如果是写操作,从缓冲区中复制数据到虚拟盘的内存中	{		memset(dev->bulk_out_buffer,0,dev->bulk_out_size);		memcpy(dev->bulk_out_buffer, bh_kmap(sbh), total);		com->cmnd[0] = 0x2A;		com->cmnd[1] = 0;		com->data_payload_size = total;		com->cmnd[2] = ((unsigned char)nLUN>>24) & 0xff;		com->cmnd[3] = ((unsigned char)nLUN>>16) & 0xff;		com->cmnd[4] = ((unsigned char)nLUN>>8) & 0xff;		com->cmnd[5] = ((unsigned char)nLUN) & 0xff;		com->cmnd[7] = (unsigned char)((total/myudisk_soft)>>8) & 0xff;		com->cmnd[8] = (unsigned char)(total/myudisk_soft) & 0xff;						com->tag = 0x12345678;		com->cmd_len = 12;		com->sc_data_direction = SCSI_DATA_WRITE;		myudisk_Bulk_transport(dev->udev,dev->interface, com, dev->bulk_out_buffer, dev->bulk_out_size, dev->bulk_in_endpointAddr, dev->bulk_out_endpointAddr);		memset(dev->bulk_out_buffer,0,dev->bulk_out_size);				} 	else {	/* can't happen */		dbg("cmd == %d is invalid\n", rw);		}	/* successful */		sbh->b_end_io(sbh,1);	//结束读写操作	kfree(com);	return 0;}/** *	myudisk_probe * *	Called by the usb core when a new device is connected that it thinks *	this driver might be interested in. */static void * myudisk_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id){	struct my_udisk *dev = NULL;	struct usb_interface *interface;	struct usb_interface_descriptor *iface_desc;	struct usb_endpoint_descriptor *endpoint;	int minor;	int buffer_size;	int i;	char name[10];	dbg("myudisk_probe()");	printk("The core has to here !!!!\n");	/* See if the device offered us matches what we can accept */	if ((udev->descriptor.idVendor != MY_UDISK_VENDOR_ID) ||	    (udev->descriptor.idProduct != MY_UDISK_PRODUCT_ID)) {		return NULL;	}		printk("drivers has successfully detected the device !!\n");		/* select a "subminor" number (part of a minor number) */	down (&minor_table_mutex);	for (minor = 0; minor < MAX_DEVICES; ++minor) {		if (minor_table[minor] == NULL)			break;	}	if (minor >= MAX_DEVICES) {		info ("Too many devices plugged in, can not handle this device.\n");		goto exit;	}	/* allocate memory for our device state and intialize it */	dev = kmalloc (sizeof(struct my_udisk), GFP_KERNEL);	if (dev == NULL) {		err ("Out of memory");		goto exit;	}	memset (dev, 0x00, sizeof (*dev));	minor_table[minor] = dev;	printk("The subminor is %d The device is %p\n",minor,minor_table[minor]);	interface = &udev->actconfig->interface[ifnum];	init_MUTEX (&dev->sem);	dev->udev = udev;	dev->interface = interface;	dev->minor = minor;	/* set up the endpoint information */	/* check out the endpoints */	iface_desc = &interface->altsetting[0];	for (i = 0; i < iface_desc->bNumEndpoints; ++i) {		endpoint = &iface_desc->endpoint[i];		if ((endpoint->bEndpointAddress & 0x80) &&		    ((endpoint->bmAttributes & 3) == 0x02)) {			/* we found a bulk in endpoint */			buffer_size = 4096;			dev->bulk_in_size = buffer_size;			dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;			dev->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);			if (!dev->bulk_in_buffer) {				err("Couldn't allocate bulk_in_buffer");				goto error;			}		}				if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&		    ((endpoint->bmAttributes & 3) == 0x02)) {			/* we found a bulk out endpoint */			dev->write_urb = usb_alloc_urb(0);			if (!dev->write_urb) {				err("No free urbs available");				goto error;			}			buffer_size = 4096;			dev->bulk_out_size = buffer_size;			dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;			dev->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL);			if (!dev->bulk_out_buffer) {				err("Couldn't allocate bulk_out_buffer");				goto error;			}			FILL_BULK_URB(dev->write_urb, udev, 				      usb_sndbulkpipe(udev, 						      endpoint->bEndpointAddress),				      dev->bulk_out_buffer, buffer_size,				      myudisk_write_bulk_callback, dev);		}	}	/* initialize the devfs node for this device and register it */	sprintf(name, "myudisk%d", dev->minor);		dev->devfs = devfs_register (usb_devfs_handle, name,				     DEVFS_FL_DEFAULT, USB_MAJOR,				     MY_UDISK_MINOR_BASE + dev->minor,				     S_IFCHR | S_IRUSR | S_IWUSR | 				     S_IRGRP | S_IWGRP | S_IROTH, 				     &myudisk_fops, NULL);///////////////////////////////////////////////////////////////////////////////This part is to read the flush's capicity and MBR information struct cmnd_struct *com;com = kmalloc (sizeof(struct cmnd_struct),GFP_KERNEL);if(com == NULL){	dbg("The memory on the com is unavailable !");	goto error;}memset(dev->bulk_in_buffer,0,dev->bulk_in_size);com->cmnd[0] = 0x25;com->tag = 0;com ->sc_data_direction = SCSI_DATA_READ ;com->cmnd[1] = 0;com->cmd_len = 12; myudisk_Bulk_transport(dev->udev, dev->interface, com, dev->bulk_in_buffer, dev->bulk_in_size, dev->bulk_in_endpointAddr, dev->bulk_out_endpointAddr);//This is to send the command and receive data from deviceprintk("To the after the read capity!");if(dev == NULL){	printk("The dev is NULL!\n");	goto error;}BLOCK_num = ( ((dev->bulk_in_buffer[0] )<< 24) | ((dev->bulk_in_buffer[1])<< 16) | ((dev->bulk_in_buffer[2]) << 8) | (dev->bulk_in_buffer[3]) ) + 1;//(__u32*)buffer;  block number LBN(n-1)myudisk_soft = ( ((dev->bulk_in_buffer[4]) << 24) | ((dev->bulk_in_buffer[5]) << 16) | ((dev->bulk_in_buffer[6]) << 8) | (dev->bulk_in_buffer[7]) );//(__u32*)buffer+4;block size.myudisk_size =  BLOCK_num * myudisk_soft;//device's capicity by bitesSECTOR_num = (myudisk_size/myudisk_hard);//device's sector numberprintk("The size is %u,The block size is %u,the num is %u",myudisk_size,myudisk_soft,BLOCK_num);memset(dev->bulk_in_buffer,0,dev->bulk_in_size);kfree(com);	//////////////////***************************************************///////////////////////////this is to read MBR information but still have some problem	__u32 nrBlock = 0;//read from the zero sector 	unsigned long size = 512;//the read block size the first 512 bites is the MBR information	struct cmnd_struct *cs;	cs = kmalloc (sizeof(struct cmnd_struct),GFP_KERNEL);	if(cs == NULL)	{		dbg("The memory on the cs is unavailable !");		goto error;	}	cs->cmnd[0] = 0x28;	cs->cmnd[1] =0;	cs->cmnd[2] = ((unsigned char)nrBlock>>24) & 0xff;	cs->cmnd[3] = ((unsigned char)nrBlock>>16) & 0xff;	cs->cmnd[4] = ((unsigned char)nrBlock>>8) & 0xff;	cs->cmnd[5] = ((unsigned char)nrBlock) & 0xff;		cs->cmnd[7] = (unsigned char)((size/myudisk_soft)>>8) & 0xff;	cs->cmnd[8] = (unsigned char)(size/myudisk_soft) & 0xff;	cs ->tag = 0x12345678;	cs->cmd_len = 12;	cs->sc_data_direction = SCSI_DATA_READ;	cs->data_payload_size = 512;	myudisk_Bulk_transport(dev->udev, dev->interface, cs, dev->bulk_in_buffer, dev->bulk_in_size, dev->bulk_in_endpointAddr, dev->bulk_out_endpointAddr);		__u32 startSector,sectorsNum;	startSector = 0;	sectorsNum  = 0;	for(i = 3; i>=1; i--)//computer the starter sector and the offset of the device	{        startSector += dev->bulk_in_buffer[0x01c6 + i];		sectorsNum  += dev->bulk_in_buffer[0x01ca + i];		startSector <<= 8;		sectorsNum  <<= 8;	}	startSector += dev->bulk_in_buffer[0x01c6];	sectorsNum  += dev->bulk_in_buffer[0x01ca];		dbg("The disk started at sector %X.\n",startSector);	dbg("The disk has %X sectors.\n",sectorsNum);	PARTION_offset = startSector;		dbg("The disk offset with %X sectors.",PARTION_offset);	printk("Next is the disk MBR and DPT information.\n");	for(i = 0; i < 512; i++){	printk("%X    ",dev->bulk_in_buffer[i]);	if(i == 445)////////////////////////////////the first 445 bites is the preboot information  the last is the partation information 		printk("\nNow is the partition table.\n");	if(i%8 == 0)		printk("\n");	}	kfree(cs);//////////////////////////////////////////////////////////////////////////////////	/* let the user know what node this device is now attached to */	info ("My UDisk device now attached to myudisk%d", dev->minor);	goto exit;	error:	myudisk_delete (dev);	dev = NULL;exit:	up (&minor_table_mutex);	return dev;}/** *	myudisk_disconnect * *	Called by the usb core when the device is removed from the system. *//*********************************************************************** * Helper routines ***********************************************************************//* Calculate the length of the data transfer (not the command) for any * given SCSI command (adapted from usb__stor_transfer_length()) */unsigned int myudisk_transfer_length(struct cmnd_struct *cs){	int doDefault = 0;	unsigned int len = 0;	/* This table tells us:	   X = command not supported	   L = return length in cmnd[4] (8 bits).	   M = return length in cmnd[8] (8 bits).	   G = return length in cmnd[3] and cmnd[4] (16 bits)	   H = return length in cmnd[7] and cmnd[8] (16 bits)	   I = return length in cmnd[8] and cmnd[9] (16 bits)	   C = return length in cmnd[2] to cmnd[5] (32 bits)	   D = return length in cmnd[6] to cmnd[9] (32 bits)	   B = return length in blocksize so we use buff_len	   R = return length in cmnd[2] to cmnd[4] (24 bits)	   S = return length in cmnd[3] to cmnd[5] (24 bits)	   T = return length in cmnd[6] to cmnd[8] (24 bits)	   U = return length in cmnd[7] to cmnd[9] (24 bits)	   0-9 = fixed return length	   V = 20 bytes	   W = 24 bytes	   Z = return length is mode dependant or not in command, use buff_len	*/	static char *lengths =	      /* 0123456789ABCDEF   0123456789ABCDEF */		"00XLZ6XZBXBBXXXB" "00LBBLG0R0L0GG0X"  /* 00-1F */		"XXXXT8XXB4B0BBBB" "ZZZ0B00HCSSZTBHH"  /* 20-3F */		"M0HHB0X000H0HH0X" "XHH0HHXX0TH0H0XX"  /* 40-5F */		"XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX"  /* 60-7F */		"XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX"  /* 80-9F */		"X0XXX00XB0BXBXBB" "ZZZ0XUIDU000XHBX"  /* A0-BF */		"XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX"  /* C0-DF */		"XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */	/* Commands checked in table:	   CHANGE_DEFINITION 40	   COMPARE 39	   COPY 18	   COPY_AND_VERIFY 3a	   ERASE 19	   ERASE_10 2c	   ERASE_12 ac	   EXCHANGE_MEDIUM a6	   FORMAT_UNIT 04	   GET_DATA_BUFFER_STATUS 34	   GET_MESSAGE_10 28	   GET_MESSAGE_12 a8	   GET_WINDOW 25   !!! Has more data than READ_CAPACITY, need to fix table	   INITIALIZE_ELEMENT_STATUS 07 !!! REASSIGN_BLOCKS luckily uses buff_len	   INQUIRY 12	   LOAD_UNLOAD 1b	   LOCATE 2b	   LOCK_UNLOCK_CACHE 36	   LOG_SELECT 4c	   LOG_SENSE 4d	   MEDIUM_SCAN 38     !!! This was M	   MODE_SELECT6 15	   MODE_SELECT_10 55	   MODE_SENSE_6 1a	   MODE_SENSE_10 5a	   MOVE_MEDIUM a5	   OBJECT_POSITION 31  !!! Same as SEARCH_DATA_EQUAL	   PAUSE_RESUME 4b	   PLAY_AUDIO_10 45	   PLAY_AUDIO_12 a5	   PLAY_AUDIO_MSF 47	   PLAY_AUDIO_TRACK_INDEX 48   	   PLAY_AUDIO_TRACK_RELATIVE_10 49	   PLAY_AUDIO_TRACK_RELATIVE_12 a9	   POSITION_TO_ELEMENT 2b      	   PRE-FETCH 34	   PREVENT_ALLOW_MEDIUM_REMOVAL 1e	   PRINT 0a             !!! Same as WRITE_6 but is always in bytes	   READ_6 08	   READ_10 28	   READ_12 a8	   READ_BLOCK_LIMITS 05	   READ_BUFFER 3c	   READ_CAPACITY 25	   READ_CDROM_CAPACITY 25	   READ_DEFECT_DATA 37	   READ_DEFECT_DATA_12 b7	   READ_ELEMENT_STATUS b8 !!! Think this is in bytes	   READ_GENERATION 29 !!! Could also be M?	   READ_HEADER 44     !!! This was L	   READ_LONG 3e	   READ_POSITION 34   !!! This should be V but conflicts with PRE-FETCH	   READ_REVERSE 0f	   READ_SUB-CHANNEL 42 !!! Is this in bytes?	   READ_TOC 43         !!! Is this in bytes?	   READ_UPDATED_BLOCK 2d	   REASSIGN_BLOCKS 07	   RECEIVE 08        !!! Same as READ_6 probably in bytes though	   RECEIVE_DIAGNOSTIC_RESULTS 1c	   RECOVER_BUFFERED_DATA 14 !!! For PRINTERs this is bytes	   RELEASE_UNIT 17	   REQUEST_SENSE 03	   REQUEST_VOLUME_ELEMENT_ADDRESS b5 !!! Think this is in bytes	   RESERVE_UNIT 16	   REWIND 01	   REZERO_UNIT 01	   SCAN 1b          !!! Conflicts with various commands, should be L	   SEARCH_DATA_EQUAL 31	   SEARCH_DATA_EQUAL_12 b1	   SEARCH_DATA_LOW 30	   SEARCH_DATA_LOW_12 b0	   SEARCH_DATA_HIGH 32	   SEARCH_DATA_HIGH_12 b2	   SEEK_6 0b         !!! Conflicts with SLEW_AND_PRINT	   SEEK_10 2b	   SEND 0a           !!! Same as WRITE_6, probably in bytes though	   SEND 2a           !!! Similar to WRITE_10 but for scanners	   SEND_DIAGNOSTIC 1d	   SEND_MESSAGE_6 0a   !!! Same as WRITE_6 - is in bytes	   SEND_MESSAGE_10 2a  !!! Same as WRITE_10 - is in bytes	   SEND_MESSAGE_12 aa  !!! Same as WRITE_12 - is in bytes	   SEND_OPC 54	   SEND_VOLUME_TAG b6 !!! Think this is in bytes	   SET_LIMITS 33	   SET_LIMITS_12 b3	   SET_WINDOW 24	   SLEW_AND_PRINT 0b !!! Conflicts with SEEK_6	   SPACE 11	   START_STOP_UNIT 1b	   STOP_PRINT 1b	   SYNCHRONIZE_BUFFER 10	   SYNCHRONIZE_CACHE 35	   TEST_UNIT_READY 00	   UPDATE_BLOCK 3d	   VERIFY 13	   VERIFY 2f	   VERIFY_12 af	   WRITE_6 0a	   WRITE_10 2a	   WRITE_12 aa	   WRITE_AND_VERIFY 2e	   WRITE_AND_VERIFY_12 ae	   WRITE_BUFFER 3b	   WRITE_FILEMARKS 10	   WRITE_LONG 3f	   WRITE_SAME 41	*/

⌨️ 快捷键说明

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