usb: gadget: storage: Support READ_TOC for MacOS

Modify READ_TOC handling to add support for both Windows and MacOS
host environments.

Change-Id: I4bf3c6a8fbec95387608869efbacb6f0537c7bbf
Signed-off-by: Ravi Vembu <raviv@motorola.com>
Moto-CRs-fixed: (CR)
Reviewed-on: http://gerrit.mot.com/864910
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver <sltawvr@motorola.com>
Tested-by: Jira Key <jirakey@motorola.com>
Submit-Approved: Jira Key <jirakey@motorola.com>
Signed-off-by: Rav(CR) Vembu <raviv@motorola.com>
Reviewed-on: https://gerrit.mot.com/944111
Reviewed-on: https://gerrit.mot.com/1167320
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Lu Chai <chailu1@motorola.com>
Reviewed-by: Jianqi Yang <yangj@motorola.com>
Submit-Approved: Jira Key
Reviewed-on: https://gerrit.mot.com/1262841
Reviewed-by: Huosheng Liao <liaohs@motorola.com>
Reviewed-on: https://gerrit.mot.com/1338861
Reviewed-on: https://gerrit.mot.com/1449077
Reviewed-on: https://gerrit.mot.com/1751139
Reviewed-by: Zonghua Liu <a17671@motorola.com>
Reviewed-on: https://gerrit.mot.com/1785339
This commit is contained in:
Ravi Vembu 2016-06-07 11:58:44 -05:00 • committed by Xiaojun Ji
commit 8b3d7897c2

View file

@ -1181,12 +1181,105 @@ static int do_read_header(struct fsg_common *common, struct fsg_buffhd *bh)
return 8;
}
struct toc_header {
u8 data_len_msb;
u8 data_len_lsb;
u8 first_track_number;
u8 last_track_number;
};
struct toc_descriptor {
u8 ctrl;
u8 adr;
u8 tno;
u8 point;
u8 min;
u8 sec;
u8 frame;
u8 zero;
u8 pmin;
u8 psec;
u8 pframe;
};
static int build_toc_response_buf(u8 *dest)
{
struct toc_header *pheader = (struct toc_header *)dest;
struct toc_descriptor *pdesc;
/* build header */
pheader->data_len_msb = 0x00;
pheader->data_len_lsb = 0x2E; /* TOC data length */
pheader->first_track_number = 0x01;
pheader->last_track_number = 0x01;
/* toc descriptor 1 */
pdesc = (struct toc_descriptor *)&dest[4];
pdesc->ctrl = 0x01;
pdesc->adr = 0x16;
pdesc->tno = 0x00;
pdesc->point = 0xA0;
pdesc->min = 0x00;
pdesc->sec = 0x00;
pdesc->frame = 0x00;
pdesc->zero = 0x00;
pdesc->pmin = 0x01; /* first track number */
pdesc->psec = 0x00;
pdesc->pframe = 0x00;
/* toc descriptor 2 */
pdesc = pdesc + 1;
pdesc->ctrl = 0x01;
pdesc->adr = 0x16;
pdesc->tno = 0x00;
pdesc->point = 0xA1;
pdesc->min = 0x00;
pdesc->sec = 0x00;
pdesc->frame = 0x00;
pdesc->zero = 0x00;
pdesc->pmin = 0x01; /* last track number */
pdesc->psec = 0x00;
pdesc->pframe = 0x00;
/* toc descriptor 3 */
pdesc = pdesc + 1;
pdesc->ctrl = 0x01;
pdesc->adr = 0x16;
pdesc->tno = 0x00;
pdesc->point = 0xA2;
pdesc->min = 0x00;
pdesc->sec = 0x00;
pdesc->frame = 0x00;
pdesc->zero = 0x00;
pdesc->pmin = 0x4F; /* pmin, psec, pframe represents */
pdesc->psec = 0x21; /* start position of lead-out */
pdesc->pframe = 0x029;
/* toc descriptor 4 */
pdesc = pdesc + 1;
pdesc->ctrl = 0x01;
pdesc->adr = 0x14;
pdesc->tno = 0x00;
pdesc->point = 0x01;
pdesc->min = 0x00;
pdesc->sec = 0x00;
pdesc->frame = 0x00;
pdesc->zero = 0x00;
pdesc->pmin = 0x00; /* pmin, psec, pframe represents */
pdesc->psec = 0x02; /* start position of track */
pdesc->pframe = 0x00;
/* return total packet length */
return (sizeof(struct toc_descriptor)*4) + sizeof(struct toc_header);
}
static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh)
{
struct fsg_lun *curlun = common->curlun;
int msf = common->cmnd[1] & 0x02;
int start_track = common->cmnd[6];
u8 *buf = (u8 *)bh->buf;
int toc_buf_len = 0;
if ((common->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */
start_track > 1) {
@ -1194,18 +1287,8 @@ static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh)
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);
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;
toc_buf_len = build_toc_response_buf(buf);
return toc_buf_len;
}
static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh)
@ -1931,8 +2014,12 @@ static int do_scsi_command(struct fsg_common *common)
goto unknown_cmnd;
common->data_size_from_cmnd =
get_unaligned_be16(&common->cmnd[7]);
/* Set bit 9 to 1 in the mask because Mac Sends a value in byte
* 9 of the READ_TOC . Windows does not set it, but changing
* the mask covers both host envs.
*/
reply = check_command(common, 10, DATA_DIR_TO_HOST,
(7<<6) | (1<<1), 1,
(0xf<<6) | (1<<1), 1,
"READ TOC");
if (reply == 0)
reply = do_read_toc(common, bh);