示例#1
0
int netmd_send_message(netmd_dev_handle *devh, unsigned char *cmd,
                       const size_t cmdlen)
{
    unsigned char pollbuf[4];
    int	len;
    libusb_device_handle *dev;

    dev = (libusb_device_handle *)devh;

    /* poll to see if we can send data */
    len = netmd_poll(dev, pollbuf, 1);
    if (len != 0) {
        netmd_log(NETMD_LOG_ERROR, "netmd_exch_message: netmd_poll failed\n");
        return (len > 0) ? NETMDERR_NOTREADY : len;
    }

    /* send data */
    netmd_log(NETMD_LOG_DEBUG, "Command:\n");
    netmd_log_hex(NETMD_LOG_DEBUG, cmd, cmdlen);
    if (libusb_control_transfer(dev, LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR |
                        LIBUSB_RECIPIENT_INTERFACE, 0x80, 0, 0, cmd, (int)cmdlen,
                        NETMD_SEND_TIMEOUT) < 0) {
        netmd_log(NETMD_LOG_ERROR, "netmd_exch_message: libusb_control_transfer failed\n");
        return NETMDERR_USB;
    }

    return 0;
}
示例#2
0
int netmd_recv_message(netmd_dev_handle *devh, unsigned char* rsp)
{
    int len;
    unsigned char pollbuf[4];
    libusb_device_handle *dev;

    dev = (libusb_device_handle *)devh;

    /* poll for data that minidisc wants to send */
    len = netmd_poll(dev, pollbuf, NETMD_RECV_TRIES);
    if (len <= 0) {
        netmd_log(NETMD_LOG_ERROR, "netmd_exch_message: netmd_poll failed\n");
        return (len == 0) ? NETMDERR_TIMEOUT : len;
    }

    /* receive data */
    if (libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR |
                        LIBUSB_RECIPIENT_INTERFACE, pollbuf[1], 0, 0, rsp, len,
                        NETMD_RECV_TIMEOUT) < 0) {
        netmd_log(NETMD_LOG_ERROR, "netmd_exch_message: libusb_control_transfer failed\n");
        return NETMDERR_USB;
    }

    netmd_log(NETMD_LOG_DEBUG, "Response:\n");
    netmd_log_hex(NETMD_LOG_DEBUG, rsp, (size_t)len);

    /* return length */
    return len;
}
示例#3
0
netmd_error netmd_secure_real_recv_track(netmd_dev_handle *dev, uint32_t length, FILE *file, size_t chunksize)
{
    uint32_t done = 0;
    unsigned char *data;
    int status;
    netmd_error error = NETMD_NO_ERROR;
    int transferred = 0;

    data = malloc(chunksize);
    while (done < length) {
        if ((length - done) < chunksize) {
            chunksize = length - done;
        }

        status = libusb_bulk_transfer((libusb_device_handle*)dev, 0x81, data, (int)chunksize, &transferred, 10000);

        if (status >= 0) {
            done += transferred;
            fwrite(data, transferred, 1, file);

            netmd_log(NETMD_LOG_DEBUG, "%.1f%%\n", (double)done/(double)length * 100);
        }
        else if (status != -LIBUSB_ERROR_TIMEOUT) {
            error = NETMD_USB_ERROR;
        }
    }
    free(data);

    return error;
}
示例#4
0
/*
  polls to see if minidisc wants to send data

  @param dev USB device handle
  @param buf pointer to poll buffer
  @param tries maximum attempts to poll the minidisc
  @return if error <0, else number of bytes that md wants to send
*/
static int netmd_poll(libusb_device_handle *dev, unsigned char *buf, int tries)
{
    int i;

    for (i = 0; i < tries; i++) {
        /* send a poll message */
        memset(buf, 0, 4);

        if (libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR |
                            LIBUSB_RECIPIENT_INTERFACE, 0x01, 0, 0, buf, 4,
                            NETMD_POLL_TIMEOUT) < 0) {
            netmd_log(NETMD_LOG_ERROR, "netmd_poll: libusb_control_transfer failed\n");
            return NETMDERR_USB;
        }

        if (buf[0] != 0) {
            break;
        }

        if (i > 0) {
            msleep(1000);
        }
    }

    return buf[2];
}
示例#5
0
netmd_error netmd_get_devname(netmd_dev_handle* devh, char* buf, size_t buffsize)
{
    int result;

    result = usb_get_string_simple((usb_dev_handle *)devh, 2, buf, buffsize);
    if (result < 0) {
        netmd_log(NETMD_LOG_ERROR, "usb_get_string_simple failed, %s (%d)\n", strerror(errno), errno);
        buf[0] = 0;
        return NETMD_USB_ERROR;
    }

    return NETMD_NO_ERROR;
}
示例#6
0
void netmd_transfer_song_packets(netmd_dev_handle *dev,
                                 netmd_track_packets *packets)
{
    netmd_track_packets *p;
    unsigned char *packet, *buf;
    size_t packet_size;
    int error;
    int transferred = 0;

    p = packets;
    while (p != NULL) {
        /* length + key + iv + data */
        packet_size = 8 + 8 + 8 + p->length;
        packet = malloc(packet_size);
        buf = packet;

        /* build packet... */
        netmd_copy_quadword_to_buffer(&buf, p->length);
        memcpy(buf, p->key, 8);
        memcpy(buf + 8, p->iv, 8);
        memcpy(buf + 16, p->data, p->length);

        /* ... send it */
        error = libusb_bulk_transfer((libusb_device_handle*)dev, 2, packet, (int)packet_size, &transferred, 10000);
        netmd_log(NETMD_LOG_DEBUG, "%d %d\n", packet_size, error);

        /* cleanup */
        free(packet);
        buf = NULL;

        if (error >= 0) {
            p = p->next;
        }
        break;
    }
}
示例#7
0
int main(int argc, char* argv[])
{
    netmd_dev_handle* devh;
    minidisc my_minidisc, *md = &my_minidisc;
    netmd_device *device_list, *netmd;
    unsigned int i = 0;
    unsigned int j = 0;
    char name[16];
    uint16_t track, playmode;
    int c;
    netmd_time time;
    netmd_error error;
    FILE *f;

    error = netmd_init(&device_list);
    if (error != NETMD_NO_ERROR) {
        printf("Error initializing netmd\n%s\n", netmd_strerror(error));
        return -1;
    }

    if (device_list == NULL) {
        puts("Found no NetMD device(s).");
        return -1;
    }

    /* pick first available device */
    netmd = device_list;

    error = netmd_open(netmd, &devh);
    if(error != NETMD_NO_ERROR)
    {
        printf("Error opening netmd\n%s\n", netmd_strerror(error));
        return -1;
    }

    error = netmd_get_devname(devh, name, 16);
    if (error != NETMD_NO_ERROR)
    {
        printf("Could not get device name\n%s\n", netmd_strerror(error));
        return -1;
    }
    printf("%s\n", name);

    netmd_initialize_disc_info(devh, md);
    printf("Disc Title: %s\n\n", md->groups[0].name);

    /* by default, log only errors */
    netmd_set_log_level(NETMD_LOG_ERROR);

    /* parse options */
    while (1) {
        c = getopt(argc, argv, "t");
        if (c == -1) {
            break;
        }
        switch (c) {
        case 't':
            netmd_set_log_level(NETMD_LOG_ALL);
            break;
        default:
            fprintf(stderr, "Unknown option '%c'\n", c);
            break;
        }
    }

    /* update argv and argc after parsing options */
    argv = &argv[optind - 1];
    argc -= (optind - 1);

    /* parse commands */
    if(argc > 1)
    {
        if(strcmp("rename", argv[1]) == 0)
        {
            i = strtoul(argv[2], NULL, 10);
            netmd_cache_toc(devh);
            netmd_set_title(devh, i & 0xffff, argv[3]);
            netmd_sync_toc(devh);
        }
        else if(strcmp("move", argv[1]) == 0)
        {
            i = strtoul(argv[2], NULL, 10);
            j = strtoul(argv[3], NULL, 10);
            netmd_move_track(devh, i & 0xffff, j & 0xffff);
        }
        else if(strcmp("groupmove", argv[1]) == 0)
        {
            i = strtoul(argv[2], NULL, 10);
            j = strtoul(argv[3], NULL, 10);
            netmd_move_group(devh, md, j & 0xffff, i & 0xffff);
        }
        else if(strcmp("write", argv[1]) == 0)
        {
            if(netmd_write_track(devh, argv[2]) < 0)
            {
                fprintf(stderr, "Error writing track %i\n", errno);
            }
        }
        else if(strcmp("newgroup", argv[1]) == 0)
        {
            netmd_create_group(devh, md, argv[2]);
        }
        else if(strcmp("settitle", argv[1]) == 0)
        {
            netmd_cache_toc(devh);
            netmd_set_disc_title(devh, argv[2], strlen(argv[2]));
            netmd_sync_toc(devh);
        }
        else if(strcmp("group", argv[1]) == 0)
        {
            i = strtoul(argv[2], NULL, 10);
            j = strtoul(argv[3], NULL, 10);
            if(!netmd_put_track_in_group(devh, md, i & 0xffff, j & 0xffff))
            {
                printf("Something screwy happened\n");
            }
        }
        else if(strcmp("retitle", argv[1]) == 0)
        {
            i = strtoul(argv[2], NULL, 10);
            netmd_set_group_title(devh, md, i, argv[3]);
        }
        else if(strcmp("play", argv[1]) == 0)
        {
            if( argc > 2 ) {
                i = strtoul(argv[2],NULL, 10);
                netmd_set_track( devh, i & 0xffff );
            }
            netmd_play(devh);
        }
        else if(strcmp("stop", argv[1]) == 0)
        {
            netmd_stop(devh);
        }
        else if(strcmp("pause", argv[1]) == 0)
        {
            netmd_pause(devh);
        }
        else if(strcmp("fforward", argv[1]) == 0)
        {
            netmd_fast_forward(devh);
        }
        else if(strcmp("rewind", argv[1]) == 0)
        {
            netmd_rewind(devh);
        }
        else if(strcmp("next", argv[1]) == 0)
        {
            netmd_track_next(devh);
        }
        else if(strcmp("previous", argv[1]) == 0)
        {
            netmd_track_previous(devh);
        }
        else if(strcmp("restart", argv[1]) == 0)
        {
            netmd_track_restart(devh);
        }
        else if(strcmp("settime", argv[1]) == 0)
        {
            track = strtoul(argv[2], (char **) NULL, 10) & 0xffff;
            if (argc > 6)
            {
                time.hour = strtoul(argv[3], (char **) NULL, 10) & 0xffff;
                time.minute = strtoul(argv[4], (char **) NULL, 10) & 0xff;
                time.second = strtoul(argv[5], (char **) NULL, 10) & 0xff;
                time.frame = strtoul(argv[6], (char **) NULL, 10) & 0xff;
            }
            else
            {
                time.hour = 0;
                time.minute = strtoul(argv[3], (char **) NULL, 10) & 0xff;
                time.second = strtoul(argv[4], (char **) NULL, 10) & 0xff;
                if (argc > 5)
                {
                    time.frame = strtoul(argv[5], (char **) NULL, 10) & 0xff;;
                }
                else
                {
                    time.frame = 0;
                }
            }

            netmd_set_time(devh, track, &time);
        }
        else if(strcmp("m3uimport", argv[1]) == 0)
        {
            import_m3u_playlist(devh, argv[2]);
        }
        else if(strcmp("delete", argv[1]) == 0)
        {
            i = strtoul(argv[2], NULL, 10);
            netmd_delete_track(devh, i & 0xffff);
        }
        else if(strcmp("deletegroup", argv[1]) == 0)
        {
            i = strtoul(argv[2], NULL, 10);
            netmd_delete_group(devh, md, i & 0xffff);
        }
        else if(strcmp("status", argv[1]) == 0) {
            print_current_track_info(devh);
        }
        else if (strcmp("raw", argv[1]) == 0) {
            send_raw_message(devh, argv[2]);
        }
        else if (strcmp("setplaymode", argv[1]) == 0) {
            playmode = 0;
            int i;
            for (i = 2; i < argc; i++) {
                if (strcmp(argv[i], "single") == 0) {
                    playmode |= NETMD_PLAYMODE_SINGLE;
                }
                else if (strcmp(argv[i], "repeat") == 0) {
                    playmode |= NETMD_PLAYMODE_REPEAT;
                }
                else if (strcmp(argv[i], "shuffle") == 0) {
                    playmode |= NETMD_PLAYMODE_SHUFFLE;
                }
            }
            printf("%x\n", playmode);
            netmd_set_playmode(devh, playmode);
        }
        else if (strcmp("capacity", argv[1]) == 0) {
            netmd_disc_capacity capacity;
            netmd_get_disc_capacity(devh, &capacity);

            printf("Recorded:  ");
            print_time(&capacity.recorded);
            printf("\nTotal:     ");
            print_time(&capacity.total);
            printf("\nAvailable: ");
            print_time(&capacity.available);
            printf("\n");
        }
        else if (strcmp("recv", argv[1]) == 0) {
            i = strtoul(argv[2], NULL, 10);
            f = fopen(argv[3], "wb");
            netmd_secure_recv_track(devh, i & 0xffff, f);
            fclose(f);
        }
        else if (strcmp("send", argv[1]) == 0) {
            netmd_error error;
            netmd_ekb ekb;
            unsigned char chain[] = {0x25, 0x45, 0x06, 0x4d, 0xea, 0xca,
                                     0x14, 0xf9, 0x96, 0xbd, 0xc8, 0xa4,
                                     0x06, 0xc2, 0x2b, 0x81, 0x49, 0xba,
                                     0xf0, 0xdf, 0x26, 0x9d, 0xb7, 0x1d,
                                     0x49, 0xba, 0xf0, 0xdf, 0x26, 0x9d,
                                     0xb7, 0x1d};
            unsigned char signature[] = {0xe8, 0xef, 0x73, 0x45, 0x8d, 0x5b,
                                         0x8b, 0xf8, 0xe8, 0xef, 0x73, 0x45,
                                         0x8d, 0x5b, 0x8b, 0xf8, 0x38, 0x5b,
                                         0x49, 0x36, 0x7b, 0x42, 0x0c, 0x58};
            unsigned char rootkey[] = {0x13, 0x37, 0x13, 0x37, 0x13, 0x37,
                                       0x13, 0x37, 0x13, 0x37, 0x13, 0x37,
                                       0x13, 0x37, 0x13, 0x37};
            netmd_keychain *keychain;
            netmd_keychain *next;
            size_t done;
            unsigned char hostnonce[8] = { 0 };
            unsigned char devnonce[8] = { 0 };
            unsigned char sessionkey[8] = { 0 };
            unsigned char kek[] = { 0x14, 0xe3, 0x83, 0x4e, 0xe2, 0xd3, 0xcc, 0xa5 };
            unsigned char contentid[] = { 0x01, 0x0F, 0x50, 0x00, 0x00, 0x04,
                                          0x00, 0x00, 0x00, 0x48, 0xA2, 0x8D,
                                          0x3E, 0x1A, 0x3B, 0x0C, 0x44, 0xAF,
                                          0x2f, 0xa0 };
            netmd_track_packets *packets = NULL;
            size_t packet_count = 0;
            struct stat stat_buf;
            unsigned char *data;
            size_t data_size;

            uint16_t track;
            unsigned char uuid[8] = { 0 };
            unsigned char new_contentid[20] = { 0 };

            error = netmd_secure_leave_session(devh);
            puts(netmd_strerror(error));

            error = netmd_secure_set_track_protection(devh, 0x01);
            puts(netmd_strerror(error));

            error = netmd_secure_enter_session(devh);
            puts(netmd_strerror(error));

            /* build ekb */
            ekb.id = 0x26422642;
            ekb.depth = 9;
            ekb.signature = malloc(sizeof(signature));
            memcpy(ekb.signature, signature, sizeof(signature));

            /* build ekb key chain */
            ekb.chain = NULL;
            for (done = 0; done < sizeof(chain); done+=16U)
            {
                next = malloc(sizeof(netmd_keychain));
                if (ekb.chain == NULL) {
                    ekb.chain = next;
                }
                else {
                    keychain->next = next;
                }
                next->next = NULL;

                next->key = malloc(16);
                memcpy(next->key, chain + done, 16);

                keychain = next;
            }

            error = netmd_secure_send_key_data(devh, &ekb);
            puts(netmd_strerror(error));

            /* cleanup */
            free(ekb.signature);
            keychain = ekb.chain;
            while (keychain != NULL) {
                next = keychain->next;
                free(keychain->key);
                free(keychain);
                keychain = next;
            }

            /* exchange nonces */
            gcry_create_nonce(hostnonce, sizeof(hostnonce));
            error = netmd_secure_session_key_exchange(devh, hostnonce, devnonce);
            puts(netmd_strerror(error));

            /* calculate session key */
            retailmac(rootkey, hostnonce, devnonce, sessionkey);

            error = netmd_secure_setup_download(devh, contentid, kek, sessionkey);
            puts(netmd_strerror(error));

            /* read source */
            stat(argv[2], &stat_buf);
            data_size = (size_t)stat_buf.st_size;
            data = malloc(data_size);
            f = fopen(argv[2], "rb");
            fseek(f, 60, SEEK_CUR);
            fread(data, data_size - 60, 1, f);
            fclose(f);
            error = netmd_prepare_packets(data, data_size-60, &packets, &packet_count, kek);
            puts(netmd_strerror(error));

            /* send to device */
            error = netmd_secure_send_track(devh, NETMD_WIREFORMAT_LP2,
                                            NETMD_DISKFORMAT_LP2,
                                            (data_size - 60) / 192, packets,
                                            packet_count, sessionkey,
                                            &track, uuid, new_contentid);
            puts(netmd_strerror(error));

            /* cleanup */
            netmd_cleanup_packets(&packets);

            /* set title */
            netmd_log(NETMD_LOG_DEBUG, "New Track: %d\n", track);
            netmd_cache_toc(devh);
            netmd_set_title(devh, track, "test");
            netmd_sync_toc(devh);

            /* commit track */
            error = netmd_secure_commit_track(devh, track, sessionkey);
            puts(netmd_strerror(error));

            /* forget key */
            error = netmd_secure_session_key_forget(devh);
            puts(netmd_strerror(error));

            /* leave session */
            error = netmd_secure_leave_session(devh);
            puts(netmd_strerror(error));
        }
        else if(strcmp("help", argv[1]) == 0)
        {
            print_syntax();
        }
        else
        {
            print_disc_info(devh, md);
            print_syntax();
        }
    }
    else
        print_disc_info(devh, md);

    netmd_clean_disc_info(md);
    netmd_close(devh);
    netmd_clean(&device_list);

    return 0;
}