From 8b3d7897c21f00bb37f8a6ff6f36cd379f235c1b Mon Sep 17 00:00:00 2001 From: Ravi Vembu Date: Tue, 7 Jun 2016 11:58:44 -0500 Subject: [PATCH] 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 Moto-CRs-fixed: (CR) Reviewed-on: http://gerrit.mot.com/864910 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Submit-Approved: Jira Key Signed-off-by: Rav(CR) Vembu 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 Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1262841 Reviewed-by: Huosheng Liao 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 Reviewed-on: https://gerrit.mot.com/1785339 --- drivers/usb/gadget/function/f_mass_storage.c | 115 ++++++++++++++++--- 1 file changed, 101 insertions(+), 14 deletions(-) diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 40730a7dbb9d..9ad998e9db33 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -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);