flope004 has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,
HEre it is my problem.
I would like to be able to read data from a USB device.
In this case, the usb device is a suunto watch (t6c) that stores heartrate,
altitude, speed, cadence.... and X data when exercising.
I have been looking around and I found this CPAN modules: Device::USB that
gives control over USB devices using the C library libusb.

Using a script included in the module, I got this information from the
device: (it is just a print from Data::Dumper).

bless( { 'location' => 0, 'dirname' => '005', 'devices' => [ bless( { 'descriptor' => { 'bcdUSB' => '2.00', 'iProduct' => 2, 'bDeviceSubClass' => 0, 'bDeviceClass' => 0, 'idProduct' => 63104, 'bcdDevice' => '4.00', 'iManufacturer' => 1, 'bMaxPacketSize0' => 8, 'iSerialNumber' => 3, 'bNumConfigurations' => 1, 'idVendor' => 1027, 'bDescriptorType' => 1, 'bDeviceProtocol' => 0 }, 'filename' => '026', 'config' => [ bless( { 'MaxPower' => 300, 'bmAttributes' => 160, 'bNumInterfaces' => 1, 'interfaces' => [ [ bless( { 'bInterfaceSubClass' => 255, 'bNumEndpoints' => 2, 'endpoints' => [ bless( { 'bmAttributes' => 2, 'wMaxPacketSize' => 64, 'bSynchAddress' => 0, 'bRefresh' => 0, 'bEndpointAddress' => 129, 'bInterval' => 0, 'bDescriptorType' => 5 }, 'Device::USB::DevEndpoint' ), bless( { 'bmAttributes' => 2, 'wMaxPacketSize' => 64, 'bSynchAddress' => 0, 'bRefresh' => 0, 'bEndpointAddress' => 2, 'bInterval' => 0, 'bDescriptorType' => 5 }, 'Device::USB::DevEndpoint' ) ], 'bInterfaceProtocol' => 255, 'iInterface' => 2, 'bInterfaceNumber' => 0, 'bDescriptorType' => 4, 'bAlternateSetting' => 0, 'bInterfaceClass' => 255 }, 'Device::USB::DevInterface' ) ] ], 'iConfiguration' => 0, 'wTotalLength' => 32, 'bConfigurationValue' => 1, 'bDescriptorType' => 2 }, 'Device::USB::DevConfig' ) ], 'device' => 9370480 }, 'Device::USB::Device' ),

So, I identified the vendor and product ID and I got information from the watch using this script:

#!/usr/bin/perl use strict; use warnings; use Device::USB; my $VENDOR = 1027; my $PRODUCT = 63104; my $usb = Device::USB->new(); my $dev = $usb->find_device( $VENDOR, $PRODUCT ); printf "Device: %04X:%04X\n", $dev->idVendor(), $dev->idProduct(); $dev->open(); print "Manufactured by ", $dev->manufacturer(), "\n", " Product: ", $dev->product(), "\n"; exit;
OUTPUT:
Device: 0403:F680 Manufactured by Suunto Product: Suunto Sports Instrument

Form here, I don't know how to interact with it to get the data stored in the device. So, any help to point me in the right direction would be fantastic.
(I have never used perl for opening/interacting with devices.)

Thanks in advance.
F

Replies are listed 'Best First'.
Re: Data adquisition from a USB device
by gwadej (Chaplain) on Apr 11, 2009 at 00:04 UTC

    I wish I could provide more help, but Device::USB only provides access to the USB library. In order to actually interface with a device, you need to know something about the protocol the device uses.

    I only know of two ways to get that:

    • find documentation on the device in question
    • use some form of usb sniffing program to watch communications with the device.

    The first option is the best if you can do it. If you have to go the sniffer route, you can do a web search for USB sniffer and find lots of options.

    If you can get the protocol information, using Device::USB is not too terribly hard. If you need further help, you can email the author of the module. He's a nice enough guy and can be helpful, even though he usually doesn't know much about any particular device.

    G. Wade

      Thanks for the quick reply!
      I don't think I can identify the protocol, though.
      How many different protocols can we expect?
      I couldn't find anything in the documentation.
      So, I used an USB sniffer (usbTrace for windows) and I captured one of the biggest packages received.
      I though you were the author

      --------- Request # 2380 ----[IN]---- URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER IRP: 0x87079008 Status: STATUS_SUCCESS (0x0) Device Object: 0x89947340 Length: 0x48 USBD Status: USBD_STATUS_SUCCESS (0x0) EndpointAddress: 0x81 PipeHandle: 0x88D24094 TransferFlags: 0x3 ( USBD_TRANSFER_DIRECTION_IN USBD_SHORT_TRANSFER_OK + ) TransferBufferLength: 0xD1 TransferBuffer: 0x875B9000 TransferBufferMDL: 0x88A877C8 UrbLink: 0x0 ** Data ** 01 60 C7 76 C5 C4 B7 FE 33 FF 39 FF 98 FF C2 FF BF FF B6 FF 45 FF 33 F +F 03 FF D7 FE 0D FF F9 FE 28 FF 6D FF 94 FF AE FF C7 FF BD FF 99 FF 3 +B FF 32 FF DC FE 15 FF 48 FF 96 FF BD FF 0E FF F8 FE 01 60 AF FF C1 F +F C7 FF 6B FF 26 FF 17 FF 02 FF F0 FE 79 FF 98 FF B3 FF A8 FF 72 FF 0 +F FF 8F FF 01 FF 99 FF A4 FF 45 FF 46 FF 1C FF BE FE 2F FF 41 FF 83 F +F B2 FF AE FF A2 FF 16 FF 09 FF 46 FF 01 60 2B FF 64 FF 9B FF A9 FF B +C FF B7 FF 3B FF 27 FF F4 FE E1 E1 FE 54 FF 37 FF 96 FF BA FF B8 FF D +2 FE CD FE 97 FF BA FF B0 FF 58 FF 2C FF 03 FF 08 FF 13 FF 75 FF 92 F +F B8 FF B9 FF 3E FF 0A 01 60 FF 8E FF 57 FF 18 FF 6D FF 88 FF 9F FF B +7 FD

        Unfortunately, there may be two different types of documentation: user docs and programmer docs. You need the programmer docs. Those are usually a bit harder to come by.

        From the information you have provided, it looks like the you could probably use the Device::USB::Device::bulk_read method. Unfortunately, without the docs, you have quite a bit of reverse-engineering to make sense of the data in that packet.

        Honestly, it would definitely be worth your time to check with the company to see if they have any programming documentation. Debugging a binary protocol is not always the best use of time.

        I though you were the author

        I am. That was supposed to be a little joke. (It turned out to be even smaller than expected.<shrug/>)

        G. Wade