CC2540: Difference between revisions

From RevSpace
Jump to navigation Jump to search
No edit summary
 
(12 intermediate revisions by the same user not shown)
Line 2: Line 2:
   |Name=CC2540
   |Name=CC2540
   |Picture=cc2540_webee.png
   |Picture=cc2540_webee.png
   |Omschrijving=Making the CC2540 BLE dongle work
   |Omschrijving=Reverse engineering the CC2540 BLE sniffer dongle
   |Status=Initializing
   |Status=Stalled
   |Contact=bertrik
   |Contact=bertrik
}}
}}
== Status ==
At this point (2017-05-09), the status is:
* it is pretty clear which commands the default sniffer firmware understands
* I wrote a little test program to dump raw BLE frames
* there is no plugin for WireShark yet


== Introduction ==
== Introduction ==
Line 74: Line 80:
   (Bus Powered)
   (Bus Powered)
</pre>
</pre>
Reading the identification from the stick with the 0xC0 command, results in the following 8-byte response
<pre>40 25 40 05 03 00 01 00</pre>
You can recognise the 2540 type number in there.


=== USB logs from Windows ===
=== USB logs from Windows ===
Line 88: Line 98:
* 0xC5, SET_POWER
* 0xC5, SET_POWER
* 0xC6, GET_POWER
* 0xC6, GET_POWER
* 0xC9, no idea, this appears in my USB logs but I can't find it in the python code
* 0xD0, START
* 0xD0, START
* 0xD1, STOP
* 0xD1, STOP
Line 93: Line 104:


== Protocol ==
== Protocol ==
[[File:cc2540_settings.png|right|thumb]]
[[File:cc2540_packet_details.png|thumb]]
[[File:cc2540_wireshark.png|thumb]]
In the windows sniffer software, it seems there are only two things communicated:
In the windows sniffer software, it seems there are only two things communicated:
* towards the stick: which radio channel to sniff, and some other radio settings
* towards the stick: which radio channel to sniff, and some other radio settings
Line 98: Line 112:


=== Configuring the radio ===
=== Configuring the radio ===
[[File:cc2540_settings.png|right|thumb]]
This appears to be done using USB control transfers.
This appears to be done using USB control transfers.


Control transfer OUT:
The following requests are sent:
* request type 0x40
{| class="wikitable"
* request 197 (0xC5)
! Request type
* value/index/length 0/4/0
! Request
* no data
! Value
! Index
! Data
! Description
|-
| 0x40 || 0xC5 || 0 || 4 || - || Set power
|-
| 0xC0 || 0xC6 || 0 || 0 || 0x00 || Get power
|-
| 0xC0 || 0xC6 || 0 || 0 || 0x04 || Get power
|-
| 0x40 || 0xC9 || 0 || 0 || - || ???
|-
| 0x40 || 0xD2 || 0 || 0 || 0x27 || Set channel
|-
| 0x40 || 0xD2 || 0 || 1 || 0x00 || Set channel
|-
| 0x40 || 0xD0 || 0 || 0 || - || Start capture
|}


Control transfer IN: check status?
Request type 0x40 is a vendor-specific device request from host-to-device.
* request type 0xC0
Request type 0xC0 is a vendor-specific device request from device-to-host.
* request 198 (0xC6)
* value/index 0/0
* data: 0x00


Control transfer IN: read until status is 0x04
=== Reading BLE frames ===
* request type 0xC0
This appears to be done using USB bulk input transfers.
* request 198 (0xC6)
* value/index 0/0
* data: 0x04


Control transfer OUT: ???
I can see a lot of similarities between the USB log and the BLE sniffer log.
* request type 0x40
* request 201 (0xC9)
* value/index 0/0
* data: -


Control transfer OUT: to set the radio channel to sniff
Each frame starts with a byte indicating the type of frame, following by two bytes indicating the length of the rest of the frame (encoded as little endian).
* request type 0x40
* request 210 (0xD2)
* value/index 0/0
* data: 0x27


Control transfer OUT: ???
==== data frames ====
* request type 0x40
The bulk USB data starts off with two bytes indicating the length of the rest of the data.
* request 210 (0xD2)
* value/index 0/1
* data: 0x00


Control transfer OUT: start capture?
In the example image on the right:
* request type 0x40
* 00: 0 means this is a data frame
* request 208 (0xD0)
* 31 00: length of rest of frame encoded in little endian = 49 bytes decimal
* value/index 0/0
* 39 04 29 54: part of the time stamp
* data: -
* 2c d6 be ..: data frame contents


=== Reading BLE frames ===
==== unknown frames (tick or 'alive'?) ====
[[File:cc2540_packet_details.png|thumb]]
The stick also returns 4-byte frames, alternating between
[[File:cc2540_wireshark.png|thumb]]
<pre>01 01 00 40</pre>
This appears to be done using USB bulk input transfers.
and
<pre>01 01 00 C0</pre>


I can see a lot of similarities between the USB log and the BLE sniffer log.
Interpretation:
The bulk USB data starts off with two bytes indicating the length of the rest of the data.
* 01: 1 means this is a frame of type 1
* 01 00: length of the rest of the frame encoded in little endian = 1 byte
* 40 or C0: unknown data byte


== Software ==
== Software ==

Latest revision as of 19:09, 13 May 2018

Project CC2540
Cc2540 webee.png
Reverse engineering the CC2540 BLE sniffer dongle
Status Stalled
Contact bertrik
Last Update 2018-05-13

Status

At this point (2017-05-09), the status is:

  • it is pretty clear which commands the default sniffer firmware understands
  • I wrote a little test program to dump raw BLE frames
  • there is no plugin for WireShark yet

Introduction

This page is about the CC2540 bluetooth low-energy sniffer dongle and getting it to work with Linux. A nice end result could be that it becomes possible to sniff directly in WireShark with this dongle.

I have such a "WeBee" dongle that can be found for about E15,- on websites like Aliexpress.

It's supposedly a CC2540 (or compatible) dongle, the USB id is 0451:16b3.

Interesting links:

Analysis

USB descriptor

When plugging this stick into a Linux machine, you can see it uses only one bulk endpoint.

Bus 001 Device 009: ID 0451:16b3 Texas Instruments, Inc. 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        32
  idVendor           0x0451 Texas Instruments, Inc.
  idProduct          0x16b3 
  bcdDevice           90.07
  iManufacturer           1 Texas Instruments
  iProduct                2 CC2540 USB Dongle
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           25
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    255 Vendor Specific Subclass
      bInterfaceProtocol    255 Vendor Specific Protocol
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               5
Device Status:     0x0000
  (Bus Powered)

Reading the identification from the stick with the 0xC0 command, results in the following 8-byte response

40 25 40 05 03 00 01 00

You can recognise the 2540 type number in there.

USB logs from Windows

This USB device does actually work with Windows:

I've captured a log of the communication over USB while the BLE is capturing bluetooth traffic from some iBeacon, using USB pcap.

In the logs, I cannot see any firmware blobs being downloaded to the stick. Probably the stick comes with a pre-loaded firmware of itself to do the BLE sniffing.

The USB control transfer request codes seem to match up with the code in https://github.com/christianpanton/ccsniffer/blob/master/ccsniffer.py

  • 0xC0, GET_IDENT: returns some kind of identifier
  • 0xC5, SET_POWER
  • 0xC6, GET_POWER
  • 0xC9, no idea, this appears in my USB logs but I can't find it in the python code
  • 0xD0, START
  • 0xD1, STOP
  • 0xD2, SET CHAN

Protocol

Cc2540 settings.png
Cc2540 packet details.png
Cc2540 wireshark.png

In the windows sniffer software, it seems there are only two things communicated:

  • towards the stick: which radio channel to sniff, and some other radio settings
  • from the stick: raw sniffed BLE frames

Configuring the radio

This appears to be done using USB control transfers.

The following requests are sent:

Request type Request Value Index Data Description
0x40 0xC5 0 4 - Set power
0xC0 0xC6 0 0 0x00 Get power
0xC0 0xC6 0 0 0x04 Get power
0x40 0xC9 0 0 - ???
0x40 0xD2 0 0 0x27 Set channel
0x40 0xD2 0 1 0x00 Set channel
0x40 0xD0 0 0 - Start capture

Request type 0x40 is a vendor-specific device request from host-to-device. Request type 0xC0 is a vendor-specific device request from device-to-host.

Reading BLE frames

This appears to be done using USB bulk input transfers.

I can see a lot of similarities between the USB log and the BLE sniffer log.

Each frame starts with a byte indicating the type of frame, following by two bytes indicating the length of the rest of the frame (encoded as little endian).

data frames

The bulk USB data starts off with two bytes indicating the length of the rest of the data.

In the example image on the right:

  • 00: 0 means this is a data frame
  • 31 00: length of rest of frame encoded in little endian = 49 bytes decimal
  • 39 04 29 54: part of the time stamp
  • 2c d6 be ..: data frame contents

unknown frames (tick or 'alive'?)

The stick also returns 4-byte frames, alternating between

01 01 00 40

and

01 01 00 C0

Interpretation:

  • 01: 1 means this is a frame of type 1
  • 01 00: length of the rest of the frame encoded in little endian = 1 byte
  • 40 or C0: unknown data byte

Software

Preliminary code can be found at https://github.com/bertrik/cc2540

It connects to the dongle and dumps raw USB packets to stdout.

This software requires libusb-1.0-dev