Linux Home
Automation

(Updated: Monday August 20, 2007)
Google
 

cm15a - Linux daemon to the X10 CM15A USB transceiver

I've quickly thrown together a page for the CM19A, X10 USB RF transceiver. Also the companion page to this document, the CM15A page. At some point I should combine both of these documents on X10's CM15A.

First if you are here looking for ready to run software for the X10 CM15A, CM19A or any of the eventual USB devices I'll have here, then you will be sadly disappointed (for now, I'm working on it). If you're here looking for nice tidy documentation on how to interface to the CM15A again you'll be disappointed (hmm, I think I'll blame X10 for not keeping it's promise of sharing some information). But if you're willing to look over my code and notes to see what I've done so far and figure out the rest then you won't be disappointed! Hopefully I will get to nice code and documentation but that's not what's available now.

I'm a bit more upset with X10 (a lot more frustrated). They had promised that they would share the technical information about the CM15A with the Open Source community and so far (hey folks this is going on 3/4+ of a year now?). Maybe we need to bug them some more at this link Active Home Professional SDK or Active Home Professional - General. Well it may not matter as I'm looking more towards Insteon. I've gotten a lot better support from them (they contact me to ask if I needed further help with their SDK). Hmm, I think I'm wasting my time with X10.

Craig Woodward has taken my cm15 driver and cm15d and modified it a bit and posted it to his cm15a page. I now have to figure out who to squeeze in the time to take his changes and integrate them with mine.

Woody Wilson has put up a web pag; Eclipse Home Automation also. On his page, in addition to the decoding he has seen, is a link to his code which uses libusb. Between the 2 of us we should be able to figure out most of the protocol.

X10 has a new interface, the CM15A. So far I've managed to write a device driver (this works on my Linux 2.4 kernel and a Linux 2.6 kernel) and a portion of the cm15d daemon (and the older version). The daemon is based on Dan Lanciani's X10d code. You need the device driver to talk to the CM15A and the cm15d daemon uses the device driver to access the device. Currently what I have working is the basic X10 command set (a1aon, a1aoff, b1boff etc.) It also has the ability to send hex codes (useful for send X10 commands). Example a1aon translates into !c 66 62 and a1aoff translates into !c 66 63 (the '!c' portion is cm15d command). The spaces are optional. For some reason I can't get the wireless to recognize my 6-in-1 remote (that may be a setup problem or it only works with new remotes).

I'm in a bit of a rush here so I'll just drop this in real quick here. Paul DeMarco has written a Perl module for the CM15A & Misterhouse. You use my device driver and his module and you can interface Misterhouse with the CM15A.

One other thing to note: you can not use the libusb code with the cm15a driver loaded. The reason is that the driver has the USB device locked (of course!). This caused some confusion on my part as I had some odd code in one of my tarballs with libusb code and code that required the driver.

So far the above has not been really tested. I've done some work over the last few weeks with it and the device driver appears to work OK. I also have some libusb based code that I was using but it was too unstable (I don't know if it's the libusb code or my code). But it does give a general idea of what needs to be read and written to the device. Woody Wilson has been kind enough to publish his code, which also uses libusb 0.1.8. As Woody puts it 'Not the cleanest code, as this was a hack from the real code I'm using'. He's also trying to share what he's learned (thanks Woody). The AHP file has a 'docs' directory where I've put together some rambling notes and traces on how I've done things under Linux. The Libusb code does write to the CM15A and it sends X10 on/off commands (I don't remember which) it also tries to setup the device. The cm15d does write to the CM15A device but I need to figure out a good way to sync the commands an replies while still allowing multiple connections to issue commands. All while waiting for the X10 commands to execute (usually about a second per command).

All the code found on this page is just a work in progress and not guaranteed to work. Back up anything important before using them!

Here is the setup of my machine that I'm developing the above code on:

  • Linux 2.6.8
  • Dist: Gentoo r3 (?)
  • CPU: AMD Sempron(tm) (2 GHz)
  • uhci_hcd loaded.
  • gcc (GCC) 3.3.4
  • Filesystems: (pertaining to USB)
    • usbfs
    • usbdevfs
    • devfs

Notes

Please note that this is a work in progress. Today's fact could be thrown out and be just plain wrong tomorrow. So if you find anything wrong, inconsistent or have a comment or recommendation to inprove the information please send it. In the mean time I'll add more info as I get a chance.

Dan Sutther's X10 Protocol document is a necessity! The CM15A has based portions of it's protocol on the CM11A's protocol.

To start to communicate with the CM15A there not really much to do. You use the USB interrupt transfers to read (endpoint 0x81) and write (endpoint 0x02) data. Under Linux I wrote a device driver (OK, so it's a big stretch of the imagination, I just changed the Labjack driver to look for the CM15A's USB Vendor and Product ID's ;-). You can then use standard reads, and writes (I'm using them with select in the cm15d daemon). Here's what you can expect back from the CM15A

Received from the CM15A

	5a    x10 commands on powerline (next byte the number of
              additional bytes to follow, not including the 5A and
	      byte count).
	5b    macro actions (start addr, end addr of macro in ram)
	5d    rf commands seen (followed by 20 (?) and 4 byte RF command)
	55    "ack"?
	a5    Power failure, send a set clock to get the CM15A to stop
              sending 5A's.

Sent to the controller

  • fb - Timers and Macros(???)
  • 9b - set time and other things
  • bb - (???)
  • db - (???)
  • 04 - House/Unit code
  • 06 - House/Function code
  • 07 - Extended command (???)

Sending an X10 on/off command

To send a single X10 on command such as P4 ON (sends on poth the power line and the RF) send the following via a usb interrupt transfer (hex bytes):

  • Send: 04 CA (2 bytes)
  • Recv: 55 (An ACK)
  • Send: 06 C2 (2 bytes)
  • Recv: 55

Please note that the first '55' doesn't always occur (not sure why yet). The '04' is the device command. The 'CA' translates into C hex = 1100 binary, a house code of P. While A hex = 1010, a unit code of 4. Or a device code of P4. The '06' is the function command. The 'C2' translates into C, a house code of P and 2 (0010), a function code of On

Extended commands (extended Status request(???))

The extended command (which the status request is a part of (???).

  • Send: 07 67 06 00 37 (Extended A1 Status request)
  • Recv: 55

For some strange reason my RR501 isn't respond (???).

Receiving an X10 on/off command

When you receive an X10 command from the power line 5A is the first byte sent. Next will be an 02 (which is eith the number of bytes that follow or a type code, I'm not sure). The next byte tells you if this is a Address (00) or Function (01) code.

D1D2D3DOn

  • 5A 02 00 A6 (D1 - address code)
  • 5A 02 00 AE (D2 - address code)
  • 5A 02 00 A2 (D3 - address code)
  • 5A 02 01 A2 (DOn - function code)

Note that the last byte translates exactly the same as the CM11A does. This command sequence is pretty straight forward.

D1D2D3DDIM

  • 5A 02 00 A6 (D1 - address code)
  • 5A 02 00 AE (D1 - address code)
  • 5A 02 00 A2 (D1 - address code)
  • 5A 03 02 0B A4 (D Preset Dim (2)- function code)

This one differs a bit. The green byte appears to be (I'm guessing) a type byte (bit 0 = Extended/Standard, bit 1 = ?, bit 2-7 = ???). The red byte is a length byte.

Housecodes and Device Codes.

The housecodes and device codes range from A to P and 1 to 16 respectively although they do not follow a binary sequence. The encoding format for these codes is as follows:

Decimal value House code Device code Binary value Hex value Function code
0 M 13 0000 0 All Units Off
1 E 5 0001 1 All Lights On
2 C 3 0010 2 On
3 K 11 0011 3 Off
4 O 15 0100 4 Dim
5 G 7 0101 5 Bright
6 A 1 0110 6 All Lights Off
7 I 9 0111 7 Extended Code
8 N 14 1000 8 Hail Request
9 F 6 1001 9 Hail Acknowledge
10 D 4 1010 A Preset Dim (1)
11 L 12 1011 B Preset Dim (2)
12 P 16 1100 C Extended Data transfer
13 H 8 1101 D Status On
14 B 2 1110 E Status Off
15 J 10 1111 F Status Request

Sending extended commands

  • 07 h7 0d vv ff
    • h is the hc as defined above
    • d is the device as defined above
    • ff and vv are as defined in the manual referenced above

examples:

07 67 06 03 3b   enable device A1 for std and extended status
07 67 06 00 37   request status from A1
07 97 03 03 3b   enable device F11 for std and extended status
07 97 0d 00 37   request status from f8
07 97 0d 21 31   dim f8 to 52%

Header:Code

The Header:Code combination is configured thus:

	   Bit: 7   6   5   4   3   2   1   0
        Header: < Dim amount    >   1  F/A E/S
  

Where:

Dim amount (dims) is a value between 0 and 22 identifying the number of dims to be transmitted (22 is equivalent to 100%)

Bit 2 is always set to '1' to ensure that the interface is able to maintain synchronization.

F/A defines whether the following byte is a function (1) or address (0).

E/S defines whether the following byte is an extended transmission (1) or a standard transmission (0).

          Bit:     7   6   5   4   3   2   1   0
          Address: < Housecode >   
          Function:< Housecode >   < Function  >
  

Note the function only operates for devices addressed with the same Housecode.

So that gives us the following:

  • 04 = 0000 0100 - no dim, address and standard transmission (an X10 address).
  • 06 = 0000 0110 - no dim, function and standard transmission (an X10 command)
  • 07 = 0000 0111 - no dim, function and extended transmission (an X10 extended command)

I haven't tried to fill in the dim portion and send the command. So I don't know if that will work. Woody tells me that he sends '06 HC/FC nn', where HC/FC is the house code and function code (such as A4 for A DIM) and the nn is the dim value.

ACK

Both Woody and I have noticed that the CM15A seems to randomly send the 0x55 packet back to commands sent. On the trace from my Windows box the CM15A sends back an ACK to the first half and the second half of an X10 command. On my Linux box I never get the ACK on the first half but I do get it on the second half. Also random ACKs appear when receiving X10 commands.

The randomness of the ACK seems a little less random now. One of the things I've been seeing is that if an RF command is reported and then a power line is reported an ACK will follow. They must both be of the same commands, a mix will not get an ACK but once a match is received an ACK will be sent.

Power Fail

Just like on the CM11A if you are getting 0x5A from the CM15A it wants it's time reset.

Set time:

	#
	#    Note:  The bit range is backwards from what you'd expect in serial 
	#    communications.  Bit 55-48 is actually the first byte transmitted
	#    etc.  To make matters worse, the bit orientation is correct within
	#    the bit range, IE bits 4-7 of byte 6 _IS_ the monitored house code.
	#    Further, bits 0 and 1 of byte 6 appear to be flipped.  I get a 
	#    "monitor status clear" if bit 0 is set.
	#    The original docs had bit 23 as part of current hours AND day.
	#    DBS Jan 1, 1997
	#
	# Bit range	Description
	# 55 to 48	timer download header (0x9b)			(byte 0)
	# 47 to 40	Current time (seconds)				(byte 1)
	# 39 to 32	Current time (minutes ranging from 0 to 119)    (byte 2)
	# 31 to 24	Current time (hours/2, ranging from 0 to 11)	(byte 3)
	# 23 to 15	Current year day (MSB is bit 15)		(byte 4+.1)
	# 14 to 8	Day mask (SMTWTFS)				(byte 5-.1)
	# 7 to 4	Monitored house code				(byte 6...)
	# 3		Reserved
	# 2		Battery timer clear flag
	# 1		Monitored status clear flag	* See note
	# 0		Timer purge flag 		* See note
	#
	#
	#
	# 319 - 1*256 + 3E = 13E = 318 ??? Is Zero the first day?
	# 254 - 275 Status changes
	# EB NJ
	# 74.25W 40.26N
	# GMT -5:00
	# 11/14/2004 09:09:48 pm Sunday (~)
	# 32 days                                                                        60 20 01
	# Monitor all codes                                                              09 21 3E Su A
	# A house code                                                                48 69 09 318
	#                                                                             ss mm hh DD dd HC xx
	  222   136     O/D ->  0x02 R  1013.507   BULK_OR_INTERRUPT_TRANSFER      9b 30 45 0a 3e 81 60 00 
	  223   136     O/U <-  0x02 R  1013.507   BULK_OR_INTERRUPT_TRANSFER      -                       0x00000000
	# 9B Time update
	# 30 Seconds (0x30 = 48)
	# 45 Minutes 0 - 119 If > 60 add an hour to the hours
	# 0a Hours*2 20 hours + 1 = 21 hours or 9 PM (???)
	# 3e Day of the year steal the high bit from the next byte -> 13E = 318 but it's day 319, off by one (???)
	# 81 Day of the week bit 1 = Sunday Bit 7 = Saturday
	# 60 Monitored House code = 0110 or A, b3 = 0 Rsvd, b2 = 0 
	# 00 don't care (???)
	#

The above is a bit complicated only because it contains a lot of data. The lines that start off with 222 & 223 are from a trace of the USB interface. Line 222 is what is sent from the PC controller to the device. Line 223 is what is sent back (just a USB ack from device to controller). The application see no data.

Basically we send the time update packet and receive nothing back, as follows:

  • Send: 9b 30 45 0a 3e 81 60 00

I also apologize for the inconsistancies. The traces come from my Windows box and I'm not sure how the time is currently set on that box. My Linux boxes are set via NTP and are very accurate.

Status command:

	#
	# Bit range	Description
	# 111 to 96	Battery timer (set to 0xffff on reset)		(Byte 0-1)
	# 95 to 88	Current time (seconds)				(Byte 2 )
	# 87 to 80	Current time (minutes ranging from 0 to 119)	(Byte 3)
	# 79 to 72	Current time (hours/2, ranging from 0 to 11)	(Byte 4)
	# 71 to 63	Current year day (MSB bit 63)			(Byte 5+)
	# 62 to 56	Day mask (SMTWTFS)				(Byte 6-)
	# 55 to 52	Monitored house code				(Byte 7 lo)
	# 51 to 48	Firmware revision level 0 to 15			(Byte 7 hi)
	# 47 to 32	Currently addressed monitored devices		(Byte 8-9)
	# 31 to 16	On / Off status of the monitored devices	(Byte 10-11)
	# 15 to 0	Dim status of the monitored devices		(Byte 12-13)
	#
	# 8B Battery time 8B40 = 2880 (0B40) High bit = sign? Low 7 bits + next byte = battery (???)
	# 40 
	# 30 Seconds
	# 45 Minutes
	# 0a hours*2
	# 3e DoY (+next high bit)
	# 81 DoW (7 bits)
	# 61 Monitored house code(high) FW rev (low)
	# 00 Current address of monitored
	# 40
	# ff On/Off stat of monitored
	# ff
	# 40 Dim stat of monitored
	# 80
	# 00 Don't care (???)
	# 00 Don't care (???)
	#
	# db Macros?
	
	#
	# Status Report : 11/14/2004 09:27 pm
	# Battery Time  			2880
	# Battery State         		1
	# Interface Clock			11/14/2004 21:27:55.000 Sun
	# Monitored House Code  		A
	# Transceived House Codes        	1,1,1,1,1,1,1,1-1,1,1,1,1,1,1,1
	# Addressed Units       		0,1,0,0,0,0,0,0-0,0,0,0,0,0,0,0
	# Monitored House Code Status   	1,1,1,1,1,1,1,1-1,1,1,1,1,1,1,1
	# Monitored House Code Dim Status       1,0,0,0,0,0,0,0-0,1,0,0,0,0,0,0
	# Monitored House Code Flag Status      0,0,0,0,0,0,0,0-0,0,0,0,0,0,0,0
	#
	  254   151     I/D ->  0x81 W  1866.674   BULK_OR_INTERRUPT_TRANSFER      -       
	  255   152     O/D ->  0x02 R  2099.990   BULK_OR_INTERRUPT_TRANSFER      8b      
	  256   152     O/U <-  0x02 R  2099.990   BULK_OR_INTERRUPT_TRANSFER      -                       0x00000000
	  257   127     I/U <-  0x81 W  2100.000   BULK_OR_INTERRUPT_TRANSFER      8b 40 37 57 0a 3e 81 61 0x00000000
	  258   153     I/D ->  0x81 W  2100.000   BULK_OR_INTERRUPT_TRANSFER      -       
	  259   129     I/U <-  0x81 W  2100.010   BULK_OR_INTERRUPT_TRANSFER      00 40 ff ff 40 80 00 00 0x00000000
	  260   154     I/D ->  0x81 W  2100.010   BULK_OR_INTERRUPT_TRANSFER      -       
	
	  261   155     O/D ->  0x02 R  2100.010   BULK_OR_INTERRUPT_TRANSFER      db 1f e0        
	  262   155     O/U <-  0x02 R  2100.010   BULK_OR_INTERRUPT_TRANSFER      -                       0x00000000
	  263   130     I/U <-  0x81 W  2100.010   BULK_OR_INTERRUPT_TRANSFER      56 25 92 37 43 92 05 61 0x00000000
	  264   156     I/D ->  0x81 W  2100.010   BULK_OR_INTERRUPT_TRANSFER      -       
	  265   131     I/U <-  0x81 W  2100.020   BULK_OR_INTERRUPT_TRANSFER      83 4a 09 83 25 2e 83 21 0x00000000
	  266   157     I/D ->  0x81 W  2100.020   BULK_OR_INTERRUPT_TRANSFER      -       
	  267   132     I/U <-  0x81 W  2100.030   BULK_OR_INTERRUPT_TRANSFER      4b 83 3d 4c ea 00 d0 1f 0x00000000
	  268   158     I/D ->  0x81 W  2100.030   BULK_OR_INTERRUPT_TRANSFER      -       
	  269   134     I/U <-  0x81 W  2100.040   BULK_OR_INTERRUPT_TRANSFER      00 d6 82 45 b6 ca c4 01 0x00000000
	  270   159     I/D ->  0x81 W  2100.040   BULK_OR_INTERRUPT_TRANSFER      -       

The above is the Status command (0x8b) you send it and get 16 bytes back. The above is what was returned from the AHP software. It confirms what is printed in Dan's document. The line which sen5 'DF 1F E0' is a bit of a puzzle and I haven't quite figured it out yet. Woody may have a clue. I'll have to recheck my notes to see what he dug up. Note that '1F E0' is 32 bytes short of 8K. And that all other 'DF' references are in 32 byte increments.

The mystery command

	  240   145     O/D ->  0x02 R  1161.771   BULK_OR_INTERRUPT_TRANSFER      bb ff ff 01 10 14 20 15 
	  241   145     O/U <-  0x02 R  1161.781   BULK_OR_INTERRUPT_TRANSFER      -                       0x00000000
	  242   121     I/U <-  0x81 W  1161.791   BULK_OR_INTERRUPT_TRANSFER      55                      0x00000000
	  243   146     I/D ->  0x81 W  1161.791   BULK_OR_INTERRUPT_TRANSFER      -       

Here's the mystery command 'BB' (followed by 7 additional bytes). I had an email where I was exchanging info with someone and they noticed a change in a setting and it changed here also. Anyway, if you send this string then you'll get back an ACK.

Yet another mystery

Another mystery command:

  • 5A 07 15 F2 FE F2 FE F2 FE (Extended command ???)

This command was received by the CM15A.

Credits

I need to give credit where credit is due. So without further adieu here are those who deserve credit for what's here:

  • The Labjack folks for there Labjack driver (which my code is directly based on) and Eric Sorton for his LegoUSB tower driver. From which their code is based on.
  • Woody Miller who got me started using the Libusb code. The faults with my libusb code are not his.
  • Dan Lanciani and his x10d code from which my cm15a get most of it's ideas (I think the cm15d code is mostly mine).
  • Dave Houston and his wealth of X10 information (hmm, missing link!). Dave's comments on the newsgroup: comp.home.automation has been very helpful in picking up various bits.

For further info email me at: ncherry@linuxha.com