Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Sony XPERIA patches for 2048 byte block on cd-rom ( crashes )

  • Loading branch information...
commit 81752c40d1cbe6b27fe0e146f4a0d9e55bb37146 1 parent 92fa2c8
@tizbac authored
View
2  .version
@@ -1 +1 @@
-1987
+2000
View
17 drivers/usb/gadget/android.c
@@ -536,9 +536,11 @@ static int mass_storage_function_init(struct android_usb_function *f,
config->fsg.nluns = 2;
config->fsg.luns[0].removable = 1;
- config->fsg.luns[0].cdrom = 0;
- config->fsg.luns[1].removable = 1;
- config->fsg.luns[1].cdrom = 1;
+ config->fsg.luns[0].cdrom = 0;
+ config->fsg.luns[1].removable = 1;
+ config->fsg.luns[1].cdrom = 1;
+ config->fsg.luns[1].ro = 1;
+
common = fsg_common_init(NULL, cdev, &config->fsg);
if (IS_ERR(common)) {
@@ -548,12 +550,19 @@ static int mass_storage_function_init(struct android_usb_function *f,
err = sysfs_create_link(&f->dev->kobj,
- &common->luns[i].dev.kobj,
+ &common->luns[0].dev.kobj,
"lun");
if (err) {
kfree(config);
return err;
}
+ err = sysfs_create_link(&f->dev->kobj,
+ &common->luns[1].dev.kobj,
+ "cdrom");
+ if (err) {
+ kfree(config);
+ return err;
+ }
config->common = common;
f->config = config;
View
68 drivers/usb/gadget/f_mass_storage.c
@@ -275,7 +275,6 @@
/* #define VERBOSE_DEBUG */
/* #define DUMP_MSGS */
-
#include <linux/blkdev.h>
#include <linux/completion.h>
#include <linux/dcache.h>
@@ -748,7 +747,7 @@ static int do_read(struct fsg_common *common)
/* Get the starting Logical Block Address and check that it's
* not too big */
if (common->cmnd[0] == SC_READ_6)
- lba = get_unaligned_be24(&common->cmnd[1]);
+ lba = (common->cmnd[1] << 16) | get_unaligned_be16(&common->cmnd[2]);
else {
lba = get_unaligned_be32(&common->cmnd[2]);
@@ -764,7 +763,11 @@ static int do_read(struct fsg_common *common)
curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return -EINVAL;
}
- file_offset = ((loff_t) lba) << 9;
+ loff_t shift_size;
+ shift_size = 9;
+ if ( curlun->cdrom )
+ shift_size = 11;
+ file_offset = ((loff_t) lba) << shift_size;
/* Carry out the file reads */
amount_left = common->data_size_from_cmnd;
@@ -802,7 +805,7 @@ static int do_read(struct fsg_common *common)
if (amount == 0) {
curlun->sense_data =
SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
- curlun->sense_data_info = file_offset >> 9;
+ curlun->sense_data_info = file_offset >> shift_size;
curlun->info_valid = 1;
bh->inreq->length = 0;
bh->state = BUF_STATE_FULL;
@@ -838,7 +841,7 @@ static int do_read(struct fsg_common *common)
/* If an error occurred, report it and its position */
if (nread < amount) {
curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
- curlun->sense_data_info = file_offset >> 9;
+ curlun->sense_data_info = file_offset >> shift_size;
curlun->info_valid = 1;
break;
}
@@ -886,7 +889,7 @@ static int do_write(struct fsg_common *common)
/* Get the starting Logical Block Address and check that it's
* not too big */
if (common->cmnd[0] == SC_WRITE_6)
- lba = get_unaligned_be24(&common->cmnd[1]);
+ lba = (common->cmnd[1] << 16) | get_unaligned_be16(&common->cmnd[2]);
else {
lba = get_unaligned_be32(&common->cmnd[2]);
@@ -911,7 +914,8 @@ static int do_write(struct fsg_common *common)
/* Carry out the file writes */
get_some_more = 1;
- file_offset = usb_offset = ((loff_t) lba) << 9;
+ loff_t shift_size = curlun->cdrom ? 11 : 9;
+ file_offset = usb_offset = ((loff_t) lba) << shift_size;
amount_left_to_req = common->data_size_from_cmnd;
amount_left_to_write = common->data_size_from_cmnd;
@@ -942,7 +946,7 @@ static int do_write(struct fsg_common *common)
get_some_more = 0;
curlun->sense_data =
SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
- curlun->sense_data_info = usb_offset >> 9;
+ curlun->sense_data_info = usb_offset >> shift_size;
curlun->info_valid = 1;
continue;
}
@@ -988,7 +992,7 @@ static int do_write(struct fsg_common *common)
/* Did something go wrong with the transfer? */
if (bh->outreq->status != 0) {
curlun->sense_data = SS_COMMUNICATION_FAILURE;
- curlun->sense_data_info = file_offset >> 9;
+ curlun->sense_data_info = file_offset >> shift_size;
curlun->info_valid = 1;
break;
}
@@ -1030,7 +1034,7 @@ static int do_write(struct fsg_common *common)
/* If an error occurred, report it and its position */
if (nwritten < amount) {
curlun->sense_data = SS_WRITE_ERROR;
- curlun->sense_data_info = file_offset >> 9;
+ curlun->sense_data_info = file_offset >> shift_size;
curlun->info_valid = 1;
break;
}
@@ -1110,10 +1114,10 @@ static int do_verify(struct fsg_common *common)
verification_length = get_unaligned_be16(&common->cmnd[7]);
if (unlikely(verification_length == 0))
return -EIO; /* No default reply */
-
+ loff_t shift_size = curlun->cdrom ? 11 : 9;
/* Prepare to carry out the file verify */
- amount_left = verification_length << 9;
- file_offset = ((loff_t) lba) << 9;
+ amount_left = verification_length << shift_size;
+ file_offset = ((loff_t) lba) << shift_size;
/* Write out all the dirty buffers before invalidating them */
fsg_lun_fsync_sub(curlun);
@@ -1139,7 +1143,7 @@ static int do_verify(struct fsg_common *common)
if (amount == 0) {
curlun->sense_data =
SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
- curlun->sense_data_info = file_offset >> 9;
+ curlun->sense_data_info = file_offset >> shift_size;
curlun->info_valid = 1;
break;
}
@@ -1166,7 +1170,7 @@ static int do_verify(struct fsg_common *common)
}
if (nread == 0) {
curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
- curlun->sense_data_info = file_offset >> 9;
+ curlun->sense_data_info = file_offset >> shift_size;
curlun->info_valid = 1;
break;
}
@@ -1193,7 +1197,8 @@ static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh)
}
buf[0] = curlun->cdrom ? TYPE_CDROM : TYPE_DISK;
- buf[1] = curlun->removable ? 0x80 : 0;
+
+ buf[1] = (curlun->removable && !curlun->cdrom) ? 0x80 : 0;
buf[2] = 2; /* ANSI SCSI level 2 */
buf[3] = 2; /* SCSI-2 INQUIRY data format */
buf[4] = 31; /* Additional length */
@@ -1274,7 +1279,8 @@ static int do_read_capacity(struct fsg_common *common, struct fsg_buffhd *bh)
put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
/* Max logical block */
- put_unaligned_be32(512, &buf[4]); /* Block length */
+ loff_t shift_size = curlun->cdrom ? 11 : 9;
+ put_unaligned_be32(1 << shift_size, &buf[4]); /* Block length */
return 8;
}
@@ -1314,18 +1320,19 @@ static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh)
curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL;
}
-
memset(buf, 0, 20);
buf[1] = (20-2); /* TOC data length */
buf[2] = 1; /* First track number */
buf[3] = 1; /* Last track number */
- buf[5] = 0x16; /* Data track, copying allowed */
+ buf[5] = 0x14; /* Data track, copying allowed */
buf[6] = 0x01; /* Only track is number 1 */
store_cdrom_address(&buf[8], msf, 0);
buf[13] = 0x16; /* Lead-out track is data */
buf[14] = 0xAA; /* Lead-out track number */
store_cdrom_address(&buf[16], msf, curlun->num_sectors);
+
+
return 20;
}
@@ -1510,7 +1517,8 @@ static int do_read_format_capacities(struct fsg_common *common,
put_unaligned_be32(curlun->num_sectors, &buf[0]);
/* Number of blocks */
- put_unaligned_be32(512, &buf[4]); /* Block length */
+ loff_t shift_size = curlun->cdrom ? 11 : 9;
+ put_unaligned_be32(1 << shift_size, &buf[4]); /* Block length */
buf[4] = 0x02; /* Current capacity */
return 12;
}
@@ -1832,7 +1840,7 @@ static int check_command(struct fsg_common *common, int cmnd_size,
if (common->data_dir != DATA_DIR_UNKNOWN)
sprintf(hdlen, ", H%c=%u", dirletter[(int) common->data_dir],
common->data_size);
- VDBG(common, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n",
+ printk( "LUN: %d , SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n",lun,
name, cmnd_size, dirletter[(int) data_dir],
common->data_size_from_cmnd, common->cmnd_size, hdlen);
@@ -1962,7 +1970,7 @@ static int do_scsi_command(struct fsg_common *common)
}
common->phase_error = 0;
common->short_packet_received = 0;
-
+ loff_t shift_size = common->curlun->cdrom ? 11 : 9;
down_read(&common->filesem); /* We're using the backing file */
switch (common->cmnd[0]) {
@@ -2024,7 +2032,7 @@ static int do_scsi_command(struct fsg_common *common)
case SC_READ_6:
i = common->cmnd[4];
- common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
+ common->data_size_from_cmnd = (i == 0 ? 256 : i) << shift_size;
reply = check_command(common, 6, DATA_DIR_TO_HOST,
(7<<1) | (1<<4), 1,
"READ(6)");
@@ -2034,7 +2042,7 @@ static int do_scsi_command(struct fsg_common *common)
case SC_READ_10:
common->data_size_from_cmnd =
- get_unaligned_be16(&common->cmnd[7]) << 9;
+ get_unaligned_be16(&common->cmnd[7]) << shift_size;
reply = check_command(common, 10, DATA_DIR_TO_HOST,
(1<<1) | (0xf<<2) | (3<<7), 1,
"READ(10)");
@@ -2044,7 +2052,7 @@ static int do_scsi_command(struct fsg_common *common)
case SC_READ_12:
common->data_size_from_cmnd =
- get_unaligned_be32(&common->cmnd[6]) << 9;
+ get_unaligned_be32(&common->cmnd[6]) << shift_size;
reply = check_command(common, 12, DATA_DIR_TO_HOST,
(1<<1) | (0xf<<2) | (0xf<<6), 1,
"READ(12)");
@@ -2142,7 +2150,7 @@ static int do_scsi_command(struct fsg_common *common)
case SC_WRITE_6:
i = common->cmnd[4];
- common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
+ common->data_size_from_cmnd = (i == 0 ? 256 : i) << shift_size;
reply = check_command(common, 6, DATA_DIR_FROM_HOST,
(7<<1) | (1<<4), 1,
"WRITE(6)");
@@ -2152,7 +2160,7 @@ static int do_scsi_command(struct fsg_common *common)
case SC_WRITE_10:
common->data_size_from_cmnd =
- get_unaligned_be16(&common->cmnd[7]) << 9;
+ get_unaligned_be16(&common->cmnd[7]) << shift_size;
reply = check_command(common, 10, DATA_DIR_FROM_HOST,
(1<<1) | (0xf<<2) | (3<<7), 1,
"WRITE(10)");
@@ -2162,7 +2170,7 @@ static int do_scsi_command(struct fsg_common *common)
case SC_WRITE_12:
common->data_size_from_cmnd =
- get_unaligned_be32(&common->cmnd[6]) << 9;
+ get_unaligned_be32(&common->cmnd[6]) << shift_size;
reply = check_command(common, 12, DATA_DIR_FROM_HOST,
(1<<1) | (0xf<<2) | (0xf<<6), 1,
"WRITE(12)");
@@ -2206,7 +2214,7 @@ static int do_scsi_command(struct fsg_common *common)
bh->state = BUF_STATE_FULL;
common->residue -= reply;
} /* Otherwise it's already set */
-
+ printk("Reply : %d\n",reply);
return 0;
}
@@ -2749,7 +2757,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
common->gadget = gadget;
common->ep0 = gadget->ep0;
common->ep0req = cdev->req;
-
+ common->cdev = cdev;
/*
* Register UMS switch for Android.
*/
View
32 drivers/usb/gadget/file_storage.c
@@ -1699,25 +1699,29 @@ static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
int msf = fsg->cmnd[1] & 0x02;
int start_track = fsg->cmnd[6];
u8 *buf = (u8 *) bh->buf;
-
+ u8 format;
+ int ret;
if ((fsg->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */
start_track > 1) {
curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL;
}
- memset(buf, 0, 20);
- buf[1] = (20-2); /* TOC data length */
- buf[2] = 1; /* First track number */
- buf[3] = 1; /* Last track number */
- buf[5] = 0x16; /* Data track, copying allowed */
- buf[6] = 0x01; /* Only track is number 1 */
- store_cdrom_address(&buf[8], msf, 0);
+ format = fsg->cmnd[2] & 0xf;
+ /*
+ * Check if CDB is old style SFF-8020i
+ * i.e. format is in 2 MSBs of byte 9
+ * Mac OS-X host sends us this.
+ */
+ if (format == 0)
+ format = (fsg->cmnd[9] >> 6) & 0x3;
- buf[13] = 0x16; /* Lead-out track is data */
- buf[14] = 0xAA; /* Lead-out track number */
- store_cdrom_address(&buf[16], msf, curlun->num_sectors);
- return 20;
+ ret = fsg_get_toc(curlun, msf, format, buf);
+ if (ret < 0) {
+ curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
+ return -EINVAL;
+ }
+ return ret;
}
@@ -2232,6 +2236,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
char hdlen[20];
struct fsg_lun *curlun;
+
/* Adjust the expected cmnd_size for protocol encapsulation padding.
* Transparent SCSI doesn't pad. */
if (protocol_is_scsi())
@@ -2489,7 +2494,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
goto unknown_cmnd;
fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
- (7<<6) | (1<<1), 1,
+ (0xf<<6) | (1<<1), 1,
"READ TOC")) == 0)
reply = do_read_toc(fsg, bh);
break;
@@ -2528,6 +2533,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
case SC_TEST_UNIT_READY:
fsg->data_size_from_cmnd = 0;
+
reply = check_command(fsg, 6, DATA_DIR_NONE,
0, 1,
"TEST UNIT READY");
View
72 drivers/usb/gadget/storage_common.c
@@ -626,7 +626,7 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
rc = (int) size;
goto out;
}
- num_sectors = size >> 9; /* File size in 512-byte blocks */
+ num_sectors = size >> (curlun->cdrom ? 11 : 9); /* File size in 512-byte blocks */
min_sectors = 1;
if (curlun->cdrom) {
num_sectors &= ~3; /* Reduce to a multiple of 2048 */
@@ -704,6 +704,76 @@ static void store_cdrom_address(u8 *dest, int msf, u32 addr)
/*-------------------------------------------------------------------------*/
+/**
+ * fsg_get_toc() - Builds a TOC with required format @format.
+ * @curlun: The LUN for which the TOC has to be built
+ * @msf: Min Sec Frame format or LBA format for address
+ * @format: TOC format code
+ * @buf: The buffer into which the TOC is built
+ *
+ * Builds a Table of Content which can be used as data for READ_TOC command.
+ * The TOC simulates a single session, single track CD-ROM mode 1 disc.
+ *
+ * Returns number of bytes written to @buf, -EINVAL if format not supported.
+ */
+static int fsg_get_toc(struct fsg_lun *curlun, int msf, int format, u8 *buf)
+{
+ int i, len;
+ switch (format) {
+ case 0:
+ /* Formatted TOC */
+ len = 4 + 2*8; /* 4 byte header + 2 descriptors */
+ memset(buf, 0, len);
+ len -= 2; /* TOC Length excludes length field */
+ buf[1] = len; /* TOC data length */
+ buf[2] = 1; /* First track number */
+ buf[3] = 1; /* Last track number */
+ buf[5] = 0x16; /* Data track, copying allowed */
+ buf[6] = 0x01; /* Only track is number 1 */
+ store_cdrom_address(&buf[8], msf, 0);
+
+ buf[13] = 0x16; /* Lead-out track is data */
+ buf[14] = 0xAA; /* Lead-out track number */
+ store_cdrom_address(&buf[16], msf, curlun->num_sectors);
+ return len;
+ break;
+
+ case 2:
+ /* Raw TOC */
+ len = 4 + 3*11; /* 4 byte header + 3 descriptors */
+ memset(buf, 0, len); /* Header + A0, A1 & A2 descriptors */
+ len -= 2; /* TOC Length excludes length field */
+ buf[1] = len; /* TOC data length */
+ buf[2] = 1; /* First complete session */
+ buf[3] = 1; /* Last complete session */
+
+ buf += 4;
+ /* fill in A0, A1 and A2 points */
+ for (i = 0; i < 3; i++) {
+ buf[0] = 1; /* Session number */
+ buf[1] = 0x16; /* Data track, copying allowed */
+ /* 2 - Track number 0 -> TOC */
+ buf[3] = 0xA0 + i; /* A0, A1, A2 point */
+ /* 4, 5, 6 - Min, sec, frame is zero */
+ buf[8] = 1; /* Pmin: last track number */
+ buf += 11; /* go to next track descriptor */
+ }
+ buf -= 11; /* go back to A2 descriptor */
+
+ /* For A2, 7, 8, 9, 10 - zero, Pmin, Psec, Pframe of Lead out */
+ store_cdrom_address(&buf[7], msf, curlun->num_sectors);
+
+ return len;
+ break;
+ default:
+ /* Multi-session, PMA, ATIP, CD-TEXT not supported/required */
+ return -EINVAL;
+ break;
+ }
+}
+
+
+
static ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr,
char *buf)
View
2  release/doit.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
[[ -d release ]] || {
echo "must be in kernel root dir"
Please sign in to comment.
Something went wrong with that request. Please try again.