A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd

scsi: add support for listing devices on Windows

Change-Id: I963028c6017796152a201791c078f672bf84a40a

+58 -2
+56
utils/scsi/rbscsi.c
··· 379 379 struct rb_scsi_devent_t *dev = malloc(sizeof(struct rb_scsi_devent_t)); 380 380 dev[0].scsi_path = NULL; 381 381 dev[0].block_path = NULL; 382 + int nr_dev = 0; 383 + /* list logical drives */ 384 + DWORD cbStrSize = GetLogicalDriveStringsA(0, NULL); 385 + LPSTR pszDrives = malloc(cbStrSize); 386 + cbStrSize = GetLogicalDriveStringsA(cbStrSize, pszDrives); 387 + /* drives are separated by a NULL character, the last drive is just a NULL one */ 388 + for(LPSTR pszDriveRoot = pszDrives; *pszDriveRoot != '\0'; 389 + pszDriveRoot += lstrlen(pszDriveRoot) + 1) 390 + { 391 + // each drive is of the form "X:\" 392 + char path[3]; 393 + path[0] = pszDriveRoot[0]; // letter 394 + path[1] = ':'; 395 + path[2] = 0; 396 + /* open drive */ 397 + rb_scsi_device_t rdev = rb_scsi_open(path, 0, NULL, NULL); 398 + if(rdev == NULL) 399 + continue; // ignore device 400 + // send an INQUIRY device to check it's actually an SCSI device and get information 401 + uint8_t inquiry_data[36]; 402 + uint8_t cdb[6] = {0x12, 0, 0, 0, sizeof(inquiry_data), 0}; // INQUIRY 403 + 404 + struct rb_scsi_raw_cmd_t raw; 405 + raw.dir = RB_SCSI_READ; 406 + raw.cdb_len = sizeof(cdb); 407 + raw.cdb = cdb; 408 + raw.buf = inquiry_data; 409 + raw.buf_len = sizeof(inquiry_data); 410 + raw.sense_len = 0; // don't bother with SENSE, this command cannot possibly fail for good reasons 411 + raw.sense = NULL; 412 + raw.tmo = 5; 413 + int ret = rb_scsi_raw_xfer(rdev, &raw); 414 + rb_scsi_close(rdev); 415 + if(ret != RB_SCSI_OK) 416 + continue; // ignore device 417 + if(raw.buf_len != (int)sizeof(inquiry_data)) 418 + continue; // ignore device (what kind of device would not return all the INQUIRY data?) 419 + 420 + /* fill device details */ 421 + dev = realloc(dev, (2 + nr_dev) * sizeof(struct rb_scsi_devent_t)); 422 + dev[nr_dev].scsi_path = strdup(path); 423 + dev[nr_dev].block_path = strdup(path); 424 + /* fill vendor/model/rev */ 425 + char info[17]; 426 + snprintf(info, sizeof(info), "%.8s", inquiry_data + 8); 427 + dev[nr_dev].vendor = strdup(info); 428 + snprintf(info, sizeof(info), "%.16s", inquiry_data + 16); 429 + dev[nr_dev].model = strdup(info); 430 + snprintf(info, sizeof(info), "%.4s", inquiry_data + 32); 431 + dev[nr_dev].rev = strdup(info); 432 + 433 + /* sentinel */ 434 + dev[++nr_dev].scsi_path = NULL; 435 + dev[nr_dev].block_path = NULL; 436 + } 437 + 382 438 return dev; 383 439 } 384 440 /* other targets */
+2 -2
utils/scsi/rbscsi.h
··· 94 94 { 95 95 /* device path to the raw SCSI device, typically: 96 96 * - Linux: /dev/sgX 97 - * - Windows: TODO 97 + * - Windows: C: 98 98 * This path can be used directly with scsi_rb_open(), and is guaranteed to 99 99 * be valid. */ 100 100 char *scsi_path; 101 101 /* device path to the corresponding block device, if it exists, typically: 102 102 * - Linux: /dev/sdX 103 - * - Windows: TODO 103 + * - Windows: C: 104 104 * If this path is not-NULL, then it can used directly with scsi_rb_open() */ 105 105 char *block_path; 106 106 /* various information about the device, can be NULL on error */