summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2020-01-29 13:27:18 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2020-01-29 13:27:18 +0100
commit05a40ab07c3f7784e62fc2651d49bb0ff735c2f3 (patch)
tree54532c723b0d5f3e97d9fc29115a0a4c04b68586
parent392db31d905c6d893c8b2bd42c03fd49332aeb3c (diff)
downloadrockbox-05a40ab.tar.gz
rockbox-05a40ab.zip
scsi: add support for listing devices on Windows
Change-Id: I963028c6017796152a201791c078f672bf84a40a
-rw-r--r--utils/scsi/rbscsi.c56
-rw-r--r--utils/scsi/rbscsi.h4
2 files changed, 58 insertions, 2 deletions
diff --git a/utils/scsi/rbscsi.c b/utils/scsi/rbscsi.c
index adfecd8d0a..b44203152f 100644
--- a/utils/scsi/rbscsi.c
+++ b/utils/scsi/rbscsi.c
@@ -379,6 +379,62 @@ struct rb_scsi_devent_t *rb_scsi_list(void)
struct rb_scsi_devent_t *dev = malloc(sizeof(struct rb_scsi_devent_t));
dev[0].scsi_path = NULL;
dev[0].block_path = NULL;
+ int nr_dev = 0;
+ /* list logical drives */
+ DWORD cbStrSize = GetLogicalDriveStringsA(0, NULL);
+ LPSTR pszDrives = malloc(cbStrSize);
+ cbStrSize = GetLogicalDriveStringsA(cbStrSize, pszDrives);
+ /* drives are separated by a NULL character, the last drive is just a NULL one */
+ for(LPSTR pszDriveRoot = pszDrives; *pszDriveRoot != '\0';
+ pszDriveRoot += lstrlen(pszDriveRoot) + 1)
+ {
+ // each drive is of the form "X:\"
+ char path[3];
+ path[0] = pszDriveRoot[0]; // letter
+ path[1] = ':';
+ path[2] = 0;
+ /* open drive */
+ rb_scsi_device_t rdev = rb_scsi_open(path, 0, NULL, NULL);
+ if(rdev == NULL)
+ continue; // ignore device
+ // send an INQUIRY device to check it's actually an SCSI device and get information
+ uint8_t inquiry_data[36];
+ uint8_t cdb[6] = {0x12, 0, 0, 0, sizeof(inquiry_data), 0}; // INQUIRY
+
+ struct rb_scsi_raw_cmd_t raw;
+ raw.dir = RB_SCSI_READ;
+ raw.cdb_len = sizeof(cdb);
+ raw.cdb = cdb;
+ raw.buf = inquiry_data;
+ raw.buf_len = sizeof(inquiry_data);
+ raw.sense_len = 0; // don't bother with SENSE, this command cannot possibly fail for good reasons
+ raw.sense = NULL;
+ raw.tmo = 5;
+ int ret = rb_scsi_raw_xfer(rdev, &raw);
+ rb_scsi_close(rdev);
+ if(ret != RB_SCSI_OK)
+ continue; // ignore device
+ if(raw.buf_len != (int)sizeof(inquiry_data))
+ continue; // ignore device (what kind of device would not return all the INQUIRY data?)
+
+ /* fill device details */
+ dev = realloc(dev, (2 + nr_dev) * sizeof(struct rb_scsi_devent_t));
+ dev[nr_dev].scsi_path = strdup(path);
+ dev[nr_dev].block_path = strdup(path);
+ /* fill vendor/model/rev */
+ char info[17];
+ snprintf(info, sizeof(info), "%.8s", inquiry_data + 8);
+ dev[nr_dev].vendor = strdup(info);
+ snprintf(info, sizeof(info), "%.16s", inquiry_data + 16);
+ dev[nr_dev].model = strdup(info);
+ snprintf(info, sizeof(info), "%.4s", inquiry_data + 32);
+ dev[nr_dev].rev = strdup(info);
+
+ /* sentinel */
+ dev[++nr_dev].scsi_path = NULL;
+ dev[nr_dev].block_path = NULL;
+ }
+
return dev;
}
/* other targets */
diff --git a/utils/scsi/rbscsi.h b/utils/scsi/rbscsi.h
index 322d94ec53..d2b4b71edb 100644
--- a/utils/scsi/rbscsi.h
+++ b/utils/scsi/rbscsi.h
@@ -94,13 +94,13 @@ struct rb_scsi_devent_t
{
/* device path to the raw SCSI device, typically:
* - Linux: /dev/sgX
- * - Windows: TODO
+ * - Windows: C:
* This path can be used directly with scsi_rb_open(), and is guaranteed to
* be valid. */
char *scsi_path;
/* device path to the corresponding block device, if it exists, typically:
* - Linux: /dev/sdX
- * - Windows: TODO
+ * - Windows: C:
* If this path is not-NULL, then it can used directly with scsi_rb_open() */
char *block_path;
/* various information about the device, can be NULL on error */