here you are , :) diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 524381a..6a5c42d 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -379,6 +379,7 @@ struct fsg_common { enum data_direction data_dir; u32 data_size; u32 data_size_from_cmnd; + u32 data_size_is_in_blocks; u32 tag; u32 residue; u32 usb_amount_left; @@ -1851,6 +1852,18 @@ static int check_command(struct fsg_common *common, int cmnd_size, char hdlen[20]; struct fsg_lun *curlun; + curlun = common->curlun; + /* Convert the data size's unit from CDB */ + if (common->data_size_is_in_blocks == 1) { + common->data_size_is_in_blocks = 0; + if (!curlun) { + DBG(common, "curlun NULL\n"); + return -EINVAL; + } + common->data_size_from_cmnd = + common->data_size_from_cmnd << curlun->blkbits; + } + hdlen[0] = 0; if (common->data_dir != DATA_DIR_UNKNOWN) sprintf(hdlen, ", H%c=%u", dirletter[(int) common->data_dir], @@ -1859,6 +1872,7 @@ static int check_command(struct fsg_common *common, int cmnd_size, name, cmnd_size, dirletter[(int) data_dir], common->data_size_from_cmnd, common->cmnd_size, hdlen); + /* * We can't reply at all until we know the correct data direction * and size. @@ -1916,17 +1930,13 @@ static int check_command(struct fsg_common *common, int cmnd_size, common->lun, lun); /* Check the LUN */ - if (common->lun >= 0 && common->lun < common->nluns) { - curlun = &common->luns[common->lun]; - common->curlun = curlun; + if (curlun) { if (common->cmnd[0] != REQUEST_SENSE) { curlun->sense_data = SS_NO_SENSE; curlun->sense_data_info = 0; curlun->info_valid = 0; } } else { - common->curlun = NULL; - curlun = NULL; common->bad_lun_okay = 0; /* @@ -2054,8 +2064,8 @@ static int do_scsi_command(struct fsg_common *common) case READ_6: i = common->cmnd[4]; - common->data_size_from_cmnd = (i == 0 ? 256 : i) << - common->curlun->blkbits; + common->data_size_from_cmnd = (i == 0 ? 256 : i); + common->data_size_is_in_blocks = 1; reply = check_command(common, 6, DATA_DIR_TO_HOST, (7<<1) | (1<<4), 1, "READ(6)"); @@ -2065,8 +2075,8 @@ static int do_scsi_command(struct fsg_common *common) case READ_10: common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]) << - common->curlun->blkbits; + get_unaligned_be16(&common->cmnd[7]); + common->data_size_is_in_blocks = 1; reply = check_command(common, 10, DATA_DIR_TO_HOST, (1<<1) | (0xf<<2) | (3<<7), 1, "READ(10)"); @@ -2076,8 +2086,8 @@ static int do_scsi_command(struct fsg_common *common) case READ_12: common->data_size_from_cmnd = - get_unaligned_be32(&common->cmnd[6]) << - common->curlun->blkbits; + get_unaligned_be32(&common->cmnd[6]); + common->data_size_is_in_blocks = 1; reply = check_command(common, 12, DATA_DIR_TO_HOST, (1<<1) | (0xf<<2) | (0xf<<6), 1, "READ(12)"); @@ -2177,8 +2187,8 @@ static int do_scsi_command(struct fsg_common *common) case WRITE_6: i = common->cmnd[4]; - common->data_size_from_cmnd = (i == 0 ? 256 : i) << - common->curlun->blkbits; + common->data_size_from_cmnd = (i == 0 ? 256 : i); + common->data_size_is_in_blocks = 1; reply = check_command(common, 6, DATA_DIR_FROM_HOST, (7<<1) | (1<<4), 1, "WRITE(6)"); @@ -2188,8 +2198,8 @@ static int do_scsi_command(struct fsg_common *common) case WRITE_10: common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]) << - common->curlun->blkbits; + get_unaligned_be16(&common->cmnd[7]); + common->data_size_is_in_blocks = 1; reply = check_command(common, 10, DATA_DIR_FROM_HOST, (1<<1) | (0xf<<2) | (3<<7), 1, "WRITE(10)"); @@ -2199,8 +2209,8 @@ static int do_scsi_command(struct fsg_common *common) case WRITE_12: common->data_size_from_cmnd = - get_unaligned_be32(&common->cmnd[6]) << - common->curlun->blkbits; + get_unaligned_be32(&common->cmnd[6]); + common->data_size_is_in_blocks = 1; reply = check_command(common, 12, DATA_DIR_FROM_HOST, (1<<1) | (0xf<<2) | (0xf<<6), 1, "WRITE(12)"); @@ -2316,7 +2326,10 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) if (common->data_size == 0) common->data_dir = DATA_DIR_NONE; common->lun = cbw->Lun; - common->curlun = &common->luns[cbw->Lun]; + if (common->lun >= 0 && common->lun < common->nluns) + common->curlun = &common->luns[common->lun]; + else + common->curlun = NULL; common->tag = cbw->Tag; return 0; } diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index e081e28..2775012 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -472,6 +472,7 @@ struct fsg_dev { enum data_direction data_dir; u32 data_size; u32 data_size_from_cmnd; + u32 data_size_is_in_blocks; u32 tag; unsigned int lun; u32 residue; @@ -2249,6 +2250,18 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, } else cmnd_size = 12; + curlun = fsg->curlun; + /* Convert the data size's unit from CDB */ + if (fsg->data_size_is_in_blocks == 1) { + fsg->data_size_is_in_blocks = 0; + if (!curlun) { + DBG(fsg, "curlun NULL\n"); + return -EINVAL; + } + fsg->data_size_from_cmnd = + fsg->data_size_from_cmnd << curlun->blkbits; + } + hdlen[0] = 0; if (fsg->data_dir != DATA_DIR_UNKNOWN) sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir], @@ -2319,15 +2332,13 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, fsg->lun = lun; // Use LUN from the command /* Check the LUN */ - if (fsg->lun >= 0 && fsg->lun < fsg->nluns) { - fsg->curlun = curlun = &fsg->luns[fsg->lun]; + if (curlun) { if (fsg->cmnd[0] != REQUEST_SENSE) { curlun->sense_data = SS_NO_SENSE; curlun->sense_data_info = 0; curlun->info_valid = 0; } } else { - fsg->curlun = curlun = NULL; fsg->bad_lun_okay = 0; /* INQUIRY and REQUEST SENSE commands are explicitly allowed @@ -2443,8 +2454,8 @@ static int do_scsi_command(struct fsg_dev *fsg) case READ_6: i = fsg->cmnd[4]; - fsg->data_size_from_cmnd = (i == 0 ? 256 : i) - << fsg->curlun->blkbits; + fsg->data_size_from_cmnd = (i == 0 ? 256 : i); + fsg->data_size_is_in_blocks = 1; if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, (7<<1) | (1<<4), 1, "READ(6)")) == 0) @@ -2453,8 +2464,8 @@ static int do_scsi_command(struct fsg_dev *fsg) case READ_10: fsg->data_size_from_cmnd = - get_unaligned_be16(&fsg->cmnd[7]) - << fsg->curlun->blkbits; + get_unaligned_be16(&fsg->cmnd[7]); + fsg->data_size_is_in_blocks = 1; if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, (1<<1) | (0xf<<2) | (3<<7), 1, "READ(10)")) == 0) @@ -2463,8 +2474,8 @@ static int do_scsi_command(struct fsg_dev *fsg) case READ_12: fsg->data_size_from_cmnd = - get_unaligned_be32(&fsg->cmnd[6]) - << fsg->curlun->blkbits; + get_unaligned_be32(&fsg->cmnd[6]); + fsg->data_size_is_in_blocks = 1; if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST, (1<<1) | (0xf<<2) | (0xf<<6), 1, "READ(12)")) == 0) @@ -2550,8 +2561,8 @@ static int do_scsi_command(struct fsg_dev *fsg) case WRITE_6: i = fsg->cmnd[4]; - fsg->data_size_from_cmnd = (i == 0 ? 256 : i) - << fsg->curlun->blkbits; + fsg->data_size_from_cmnd = (i == 0 ? 256 : i); + fsg->data_size_is_in_blocks = 1; if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST, (7<<1) | (1<<4), 1, "WRITE(6)")) == 0) @@ -2560,8 +2571,8 @@ static int do_scsi_command(struct fsg_dev *fsg) case WRITE_10: fsg->data_size_from_cmnd = - get_unaligned_be16(&fsg->cmnd[7]) - << fsg->curlun->blkbits; + get_unaligned_be16(&fsg->cmnd[7]); + fsg->data_size_is_in_blocks = 1; if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST, (1<<1) | (0xf<<2) | (3<<7), 1, "WRITE(10)")) == 0) @@ -2570,8 +2581,8 @@ static int do_scsi_command(struct fsg_dev *fsg) case WRITE_12: fsg->data_size_from_cmnd = - get_unaligned_be32(&fsg->cmnd[6]) - << fsg->curlun->blkbits; + get_unaligned_be32(&fsg->cmnd[6]); + fsg->data_size_is_in_blocks = 1; if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST, (1<<1) | (0xf<<2) | (0xf<<6), 1, "WRITE(12)")) == 0) @@ -2688,6 +2699,12 @@ static int get_next_command(struct fsg_dev *fsg) struct fsg_buffhd *bh; int rc = 0; + /* Update current lun */ + if (fsg->lun >= 0 && fsg->lun < fsg->nluns) + fsg->curlun = &fsg->luns[fsg->lun]; + else + fsg->curlun = NULL; + if (transport_is_bbb()) { /* Wait for the next buffer to become available */ Thanks Yuping Luo On Fri, Oct 14, 2011 at 9:45 AM, Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote: > On Fri, 14 Oct 2011, Barry Song wrote: > >> > Checking the LUN value and doing the bit shifts in a single place is >> > better than doing them repeatedly in many different command handlers. >> >> i don't see too much benefit we can get from adding a new flag. might >> it is clearer. >> if you prefer that way, we can take. > > Sure, go ahead. Let's compare the new patch with this one; I think it > will look better. > > Alan Stern > > -- > To unsubscribe from this list: send the line "unsubscribe linux-usb" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html