Original address:
http://hengch.blog.163.com/blog/static/1078006720086141327970
In "USB Series III", we implemented a series of SCSI commands. In this series, we are going to implement the command to write sectors to the USB flash drive, so this article is relatively easy, mainly giving an implementation source code.
In "USB Series III", the SCSI commands we implemented are: INQUIRY, READ CAPACITY(10), TEST UNIT READY, REQUEST SENSE, READ(10); all are some read commands, so they will not damage the content of the USB flash drive. On page 29 of document SBC-2, there is a table of SCSI commands. In this table, all commands with TYPE "M" are commands that SCSI devices must implement. These commands are:
Num Command Name Operation Code Type Reference
-----------------------------------------------------------------
1 FORMAT UNIT 04h M SBC-2
2 INQUIRY 12h M SPC-3
3 READ(6) 08h M SBC-2
4 READ(10) 28h M SBC-2
5 READ(16) 88h M SBC-2
6 READ CAPACITY(10) 25h M SBC-2
7 READ CAPACITY(16) 9Eh/10h M SBC-2
8 REQUEST SENSE 03h M SPC-3
9 SEND DIAGNOSTIC 1Dh M SPC-3
10 TEST UNIT READY 00h M SPC-3
11 WRITE(10) 2Ah O SBC-2
The last command here is not a mandatory one required by SBC-2, but optional. However, if we don't implement it, the operation of the USB flash drive will be much less interesting. We don't plan to implement the commands with serial numbers 1, 3, 5, 7, and 9. READ(6), READ(16), and READ(10) are very similar, just the length of LBA is different. If needed to implement, refer to READ(10). The FORMAT and SEND DIAGNOSTIC commands are not meaningful for USB flash drives using the chip, but they are meaningful for hard disks. So in this article, we only need to implement an important WRTE(10) to write data to the USB flash drive. We need to prepare a USB flash drive with no useful data because we are going to change its content.
Download address of WRITE(10) source code:
http://blog.hengch.com/source/usb-write.zip
In the program, we, just like in the program of "USB Series III", first reset, then get the maximum LUN. This step is not necessary. Then we send the WRITE(10) command to the device. Note that this is an OUT transaction, so CBW_FLAGS=0X00 instead of 0X80 as before. After sending the WRITE(10) command, we also need to send the data to be written to the device. Each time 64 bytes, and one sector of 512 bytes requires starting 8 OUT transactions. This work is done by the function putData. Each time 64 bytes sent, we write 0--63 respectively. In the program, we write these data to the sector with LBA=100. After writing, we use the READ(10) command introduced in "USB Series III" to read the same sector again. We will see the result we expect. Since we have cleared the buffer to 0 before reading, we are confident that the data we read is real.
Up to here, we have introduced all the main commands to control the USB flash drive. Using DOSUSB, we have the possibility to write a simple driver for the USB flash drive. But maybe we don't know how to write a driver under DOS yet. Starting from the next article, we will temporarily put aside the USB series articles and introduce how to write a driver under DOS.
http://hengch.blog.163.com/blog/static/1078006720086141327970
In "USB Series III", we implemented a series of SCSI commands. In this series, we are going to implement the command to write sectors to the USB flash drive, so this article is relatively easy, mainly giving an implementation source code.
In "USB Series III", the SCSI commands we implemented are: INQUIRY, READ CAPACITY(10), TEST UNIT READY, REQUEST SENSE, READ(10); all are some read commands, so they will not damage the content of the USB flash drive. On page 29 of document SBC-2, there is a table of SCSI commands. In this table, all commands with TYPE "M" are commands that SCSI devices must implement. These commands are:
Num Command Name Operation Code Type Reference
-----------------------------------------------------------------
1 FORMAT UNIT 04h M SBC-2
2 INQUIRY 12h M SPC-3
3 READ(6) 08h M SBC-2
4 READ(10) 28h M SBC-2
5 READ(16) 88h M SBC-2
6 READ CAPACITY(10) 25h M SBC-2
7 READ CAPACITY(16) 9Eh/10h M SBC-2
8 REQUEST SENSE 03h M SPC-3
9 SEND DIAGNOSTIC 1Dh M SPC-3
10 TEST UNIT READY 00h M SPC-3
11 WRITE(10) 2Ah O SBC-2
The last command here is not a mandatory one required by SBC-2, but optional. However, if we don't implement it, the operation of the USB flash drive will be much less interesting. We don't plan to implement the commands with serial numbers 1, 3, 5, 7, and 9. READ(6), READ(16), and READ(10) are very similar, just the length of LBA is different. If needed to implement, refer to READ(10). The FORMAT and SEND DIAGNOSTIC commands are not meaningful for USB flash drives using the chip, but they are meaningful for hard disks. So in this article, we only need to implement an important WRTE(10) to write data to the USB flash drive. We need to prepare a USB flash drive with no useful data because we are going to change its content.
Download address of WRITE(10) source code:
http://blog.hengch.com/source/usb-write.zip
In the program, we, just like in the program of "USB Series III", first reset, then get the maximum LUN. This step is not necessary. Then we send the WRITE(10) command to the device. Note that this is an OUT transaction, so CBW_FLAGS=0X00 instead of 0X80 as before. After sending the WRITE(10) command, we also need to send the data to be written to the device. Each time 64 bytes, and one sector of 512 bytes requires starting 8 OUT transactions. This work is done by the function putData. Each time 64 bytes sent, we write 0--63 respectively. In the program, we write these data to the sector with LBA=100. After writing, we use the READ(10) command introduced in "USB Series III" to read the same sector again. We will see the result we expect. Since we have cleared the buffer to 0 before reading, we are confident that the data we read is real.
Up to here, we have introduced all the main commands to control the USB flash drive. Using DOSUSB, we have the possibility to write a simple driver for the USB flash drive. But maybe we don't know how to write a driver under DOS yet. Starting from the next article, we will temporarily put aside the USB series articles and introduce how to write a driver under DOS.

DigestI