diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2017-06-18 13:06:12 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2017-06-18 13:37:26 +0200 |
commit | 91ede1ea08ae217ccd22cdc936e474cdc0a4466c (patch) | |
tree | 3e8b5b58b64149243d027a0d66c3bef6ef630b24 | |
parent | 8d5dcd395d0150abf4ec7b5a721ff003e2f9772d (diff) | |
download | rockbox-91ede1ea08ae217ccd22cdc936e474cdc0a4466c.tar.gz rockbox-91ede1ea08ae217ccd22cdc936e474cdc0a4466c.zip |
nwztools/scsitool: fix devinfo, add dhp
The devinfo request returned the raw data, now the tool prints the various
fields. Also add support for the dhp (destination/headphones/color ...): this
one is untested because it's only supported starting from A10 or A20. There is
still a problem with the dpcc prop: although it should work for DEVINFO, it does
not, despite the fact that the get_dev_info command works and is internally (on
the Sony) translated into a dpcc request. I keep the code just in case.
Change-Id: I5aa8ef4afb0b11d3c0ddfa3d38f3e737ee1aff66
-rw-r--r-- | utils/nwztools/scsitools/scsitool.c | 75 |
1 files changed, 69 insertions, 6 deletions
diff --git a/utils/nwztools/scsitools/scsitool.c b/utils/nwztools/scsitools/scsitool.c index 6c3527713e..a90729a3d5 100644 --- a/utils/nwztools/scsitools/scsitool.c +++ b/utils/nwztools/scsitools/scsitool.c | |||
@@ -512,17 +512,48 @@ int get_dnk_nvp(int argc, char **argv) | |||
512 | return 0; | 512 | return 0; |
513 | } | 513 | } |
514 | 514 | ||
515 | struct dpcc_devinfo_t | ||
516 | { | ||
517 | uint8_t vendor_identification[8]; | ||
518 | uint8_t product_identification[16]; | ||
519 | uint8_t product_revision[4]; | ||
520 | uint8_t product_sub_revision[4]; | ||
521 | uint8_t storage_size[4]; | ||
522 | uint8_t serial_number[16]; | ||
523 | uint8_t vendor_specific[32]; | ||
524 | } __attribute__((packed)); | ||
525 | |||
526 | void dpcc_print_devinfo(void *buffer, int buf_size) | ||
527 | { | ||
528 | if(buf_size < sizeof(struct dpcc_devinfo_t)) | ||
529 | { | ||
530 | cprintf(GREY, "Cannot parse DEVINFO: buffer too small\n"); | ||
531 | return; | ||
532 | } | ||
533 | struct dpcc_devinfo_t *devinfo = buffer; | ||
534 | cprintf_field("Vendor identification: ", "%.8s\n", devinfo->vendor_identification); | ||
535 | cprintf_field("Product identification: ", "%.16s\n", devinfo->product_identification); | ||
536 | cprintf_field("Product revision: ", "%.4s\n", devinfo->product_revision); | ||
537 | cprintf_field("Product sub revision: ", "%.4s\n", devinfo->product_sub_revision); | ||
538 | cprintf_field("Storage size: ", "%.4s\n", devinfo->storage_size); | ||
539 | cprintf_field("Serial number: ", "%.32s\n", devinfo->serial_number); | ||
540 | cprintf_field("Vendor specific: ", "%.32s\n", devinfo->vendor_specific); | ||
541 | } | ||
542 | |||
543 | typedef void (*dpcc_print_func_t)(void *buffer, int buf_size); | ||
544 | |||
515 | struct dpcc_prop_t | 545 | struct dpcc_prop_t |
516 | { | 546 | { |
517 | char *user_name; | 547 | char *user_name; |
518 | char name[7]; | 548 | char name[7]; |
519 | uint8_t cdb1; | 549 | uint8_t cdb1; // flags: bit 0 means size flag (means size in paragraph) |
520 | int size; | 550 | int size; |
551 | dpcc_print_func_t print_func; | ||
521 | }; | 552 | }; |
522 | 553 | ||
523 | struct dpcc_prop_t dpcc_prop_list[] = | 554 | struct dpcc_prop_t dpcc_prop_list[] = |
524 | { | 555 | { |
525 | { "dev_info", "DEVINFO", 0, 0x80 }, | 556 | { "dev_info", "DEVINFO", 0, 0x80, dpcc_print_devinfo }, |
526 | /* there are more but they are very obscure */ | 557 | /* there are more but they are very obscure */ |
527 | }; | 558 | }; |
528 | 559 | ||
@@ -534,7 +565,7 @@ int do_dpcc_cmd(uint32_t cmd, struct dpcc_prop_t *prop, void *buffer, int *buffe | |||
534 | cdb[2] = cmd; | 565 | cdb[2] = cmd; |
535 | if(cmd == 0) | 566 | if(cmd == 0) |
536 | { | 567 | { |
537 | strncpy((char *)(cdb + 3), prop->name, 7); // warning: erase cdb[10] ! | 568 | memcpy((char *)(cdb + 3), prop->name, 7); |
538 | cdb[1] = prop->cdb1; | 569 | cdb[1] = prop->cdb1; |
539 | if(prop->cdb1 & 1) | 570 | if(prop->cdb1 & 1) |
540 | cdb[10] = (*buffer_size + 15) / 16; | 571 | cdb[10] = (*buffer_size + 15) / 16; |
@@ -575,7 +606,7 @@ int get_dpcc_prop(int argc, char **argv) | |||
575 | for(unsigned i = 0; i < NR_DPCC_PROPS; i++) | 606 | for(unsigned i = 0; i < NR_DPCC_PROPS; i++) |
576 | if(strcmp(dpcc_prop_list[i].user_name, argv[0]) == 0) | 607 | if(strcmp(dpcc_prop_list[i].user_name, argv[0]) == 0) |
577 | prop = dpcc_prop_list[i]; | 608 | prop = dpcc_prop_list[i]; |
578 | if(prop.user_name[0] == 0) | 609 | if(prop.user_name == 0) |
579 | { | 610 | { |
580 | cprintf(GREY, "Unknown property '%s'\n", argv[0]); | 611 | cprintf(GREY, "Unknown property '%s'\n", argv[0]); |
581 | return 1; | 612 | return 1; |
@@ -641,7 +672,35 @@ int get_dev_info(int argc, char **argv) | |||
641 | (void )argv; | 672 | (void )argv; |
642 | uint8_t cdb[12] = {0xfc, 0, 0x20, 'd', 'b', 'm', 'n', 0, 0x80, 0, 0, 0}; | 673 | uint8_t cdb[12] = {0xfc, 0, 0x20, 'd', 'b', 'm', 'n', 0, 0x80, 0, 0, 0}; |
643 | 674 | ||
644 | char *buffer = malloc(0x81); | 675 | char *buffer = malloc(0x80); |
676 | int buffer_size = 0x80; | ||
677 | uint8_t sense[32]; | ||
678 | int sense_size = 32; | ||
679 | |||
680 | int ret = do_scsi(cdb, 12, DO_READ, sense, &sense_size, buffer, &buffer_size); | ||
681 | if(ret < 0) | ||
682 | return ret; | ||
683 | ret = do_sense_analysis(ret, sense, sense_size); | ||
684 | if(ret) | ||
685 | { | ||
686 | cprintf(GREY, "An error occured during request\n"); | ||
687 | return ret; | ||
688 | } | ||
689 | buffer[buffer_size] = 0; | ||
690 | cprintf_field("Raw device info:", "\n"); | ||
691 | print_hex(buffer, buffer_size); | ||
692 | // the 16 first bytes are 'DEVINFO', 0x80, followed by zeroes | ||
693 | dpcc_print_devinfo(buffer + 16, buffer_size - 16); | ||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | int get_dhp(int argc, char **argv) | ||
698 | { | ||
699 | (void) argc; | ||
700 | (void )argv; | ||
701 | uint8_t cdb[12] = {0xfc, 0, 'D', 'd', 'h', 'p', 0, 0, 0, 0, 0, 0}; | ||
702 | |||
703 | char *buffer = malloc(0x80); | ||
645 | int buffer_size = 0x80; | 704 | int buffer_size = 0x80; |
646 | uint8_t sense[32]; | 705 | uint8_t sense[32]; |
647 | int sense_size = 32; | 706 | int sense_size = 32; |
@@ -651,9 +710,12 @@ int get_dev_info(int argc, char **argv) | |||
651 | return ret; | 710 | return ret; |
652 | ret = do_sense_analysis(ret, sense, sense_size); | 711 | ret = do_sense_analysis(ret, sense, sense_size); |
653 | if(ret) | 712 | if(ret) |
713 | { | ||
714 | cprintf(GREY, "An error occured during request\n"); | ||
654 | return ret; | 715 | return ret; |
716 | } | ||
655 | buffer[buffer_size] = 0; | 717 | buffer[buffer_size] = 0; |
656 | cprintf_field("Device Info:", "\n"); | 718 | cprintf_field("Destination/Headphones:", "\n"); |
657 | print_hex(buffer, buffer_size); | 719 | print_hex(buffer, buffer_size); |
658 | return 0; | 720 | return 0; |
659 | } | 721 | } |
@@ -839,6 +901,7 @@ struct cmd_t cmd_list[] = | |||
839 | { "get_dpcc_prop", "Get DPCC property", get_dpcc_prop }, | 901 | { "get_dpcc_prop", "Get DPCC property", get_dpcc_prop }, |
840 | { "get_user_time", "Get user time", get_user_time }, | 902 | { "get_user_time", "Get user time", get_user_time }, |
841 | { "get_dev_info", "Get device info", get_dev_info }, | 903 | { "get_dev_info", "Get device info", get_dev_info }, |
904 | { "get_dhp", "Get destination headphones", get_dhp }, | ||
842 | { "do_fw_upgrade", "Do a firmware upgrade", do_fw_upgrade }, | 905 | { "do_fw_upgrade", "Do a firmware upgrade", do_fw_upgrade }, |
843 | { "dest_tool", "Get/Set destination and sound pressure regulation", do_dest }, | 906 | { "dest_tool", "Get/Set destination and sound pressure regulation", do_dest }, |
844 | }; | 907 | }; |