Rather than hard coding the base Energenie address use the serial number
to encode it. Also report it as part of the USB descriptor making it
easier to match against for udev etc.
#define CMD_OFF 0xfd
#define CMD_SET_SERIAL 0xfa
#define CMD_OFF 0xfd
#define CMD_SET_SERIAL 0xfa
-/* Energenie 24 bit address , last 4 all 0 for code */
-#define ENER_ADDR 0x123450
-
-uchar serno_read = 0;
-uchar serno[6];
+int serno_str[] = {
+ USB_STRING_DESCRIPTOR_HEADER(5),
+ '1', '2', '3', '4', '5',
+};
+uint32_t serno;
unsigned long cmd = 0;
int repeat = 0, wait = 0;
unsigned long cmd = 0;
int repeat = 0, wait = 0;
0xc0 /* END_COLLECTION */
};
0xc0 /* END_COLLECTION */
};
+inline char hexdigit(int i)
+{
+ return (i < 10) ? ('0' + i) : ('A' - 10 + i);
+}
+
+inline int digithex(char i)
+{
+ if (i >= '0' && i <= '9')
+ return i - '0';
+
+ if (i >= 'A' && i <= 'F')
+ return i - 'A' + 10;
+
+ if (i >= 'a' && i <= 'f')
+ return i - 'a' + 10;
+
+ return 0;
+}
+
- if (!serno_read) {
- eeprom_read_block(serno, 0, 6);
- if (serno[0] == 0xff) {
- /* If the EEPROM is blank, return a default serial # */
- serno[0] = 'U';
- serno[1] = 'N';
- serno[2] = 'S';
- serno[3] = 'E';
- serno[4] = 'T';
- serno[5] = 0;
- }
- serno_read = 1;
+ eeprom_read_block(&serno, 0, 4);
+ if (serno == 0xffffffff) {
+ /* If the EEPROM is blank, return a default serial # */
+ serno_str[1] = '1';
+ serno_str[2] = '2';
+ serno_str[3] = '3';
+ serno_str[4] = '4';
+ serno_str[5] = '5';
+ } else {
+ serno_str[1] = hexdigit((serno >> 20) & 0xF);
+ serno_str[2] = hexdigit((serno >> 16) & 0xF);
+ serno_str[3] = hexdigit((serno >> 12) & 0xF);
+ serno_str[4] = hexdigit((serno >> 8) & 0xF);
+ serno_str[5] = hexdigit((serno >> 4) & 0xF);
+ serno = 0;
+ for (i = 0; i < 5; i++) {
+ serno |= digithex(buf[i]);
+ serno <<= 4;
+ }
+
/*
* I have no idea why this gets stored 3 times, but the original
* firmware does it.
*/
/*
* I have no idea why this gets stored 3 times, but the original
* firmware does it.
*/
- eeprom_write_block(buf, (void *) 0x00, len);
- eeprom_write_block(buf, (void *) 0x40, len);
- eeprom_write_block(buf, (void *) 0x80, len);
+ eeprom_write_block(&serno, (void *) 0x00, 4);
+ eeprom_write_block(&serno, (void *) 0x40, 4);
+ eeprom_write_block(&serno, (void *) 0x80, 4);
- for (i = 0; i < 6; i++) {
- serno[i] = buf[i];
+ for (i = 0; i < 5; i++) {
+ serno_str[i + 1] = buf[i];
+usbMsgLen_t usbFunctionDescriptor(usbRequest_t *rq)
+{
+ if (rq->wValue.bytes[1] == USBDESCR_STRING &&
+ rq->wValue.bytes[0] == 3) {
+ usbMsgPtr = (usbMsgPtr_t) serno_str;
+ return sizeof(serno_str);
+ }
+ return 0;
+}
+
uchar usbFunctionRead(uchar *data, uchar len)
{
uchar i;
if (len != 0) {
uchar usbFunctionRead(uchar *data, uchar len)
{
uchar i;
if (len != 0) {
- fetch_serno();
- for (i = 0; i < 6; i++) {
- data[i] = serno[i];
+ for (i = 0; i < 5; i++) {
+ data[i] = serno_str[i + 1];
+ data[5] = data[6] = data[7] = 0;
if (PORTB & (1 << PB0)) {
data[7] = 1;
}
if (PORTB & (1 << PB0)) {
data[7] = 1;
}
uchar usbFunctionWrite(uchar *data, uchar len)
{
if (data[0] == CMD_ALL_ON) {
uchar usbFunctionWrite(uchar *data, uchar len)
{
if (data[0] == CMD_ALL_ON) {
wait = 200;
repeat = 5;
} else if (data[0] == CMD_ALL_OFF) {
wait = 200;
repeat = 5;
} else if (data[0] == CMD_ALL_OFF) {
wait = 10;
repeat = 5;
} else if (data[0] == CMD_ON) {
wait = 200;
switch (data[1]) {
case 1:
wait = 10;
repeat = 5;
} else if (data[0] == CMD_ON) {
wait = 200;
switch (data[1]) {
case 1:
repeat = 5;
break;
case 2:
repeat = 5;
break;
case 2:
repeat = 5;
break;
case 3:
repeat = 5;
break;
case 3:
repeat = 5;
break;
case 4:
repeat = 5;
break;
case 4:
repeat = 5;
break;
default:
repeat = 5;
break;
default:
wait = 200;
switch (data[1]) {
case 1:
wait = 200;
switch (data[1]) {
case 1:
repeat = 5;
break;
case 2:
repeat = 5;
break;
case 2:
repeat = 5;
break;
case 3:
repeat = 5;
break;
case 3:
repeat = 5;
break;
case 4:
repeat = 5;
break;
case 4:
repeat = 5;
break;
default:
repeat = 5;
break;
default:
usbInit();
usbDeviceDisconnect();
usbInit();
usbDeviceDisconnect();
#define USB_CFG_DESCR_PROPS_STRING_0 0
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0
#define USB_CFG_DESCR_PROPS_STRING_0 0
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0
-#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0
+#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER (USB_PROP_IS_DYNAMIC | USB_PROP_IS_RAM)
#define USB_CFG_DESCR_PROPS_HID 0
#define USB_CFG_DESCR_PROPS_HID_REPORT 0
#define USB_CFG_DESCR_PROPS_UNKNOWN 0
#define USB_CFG_DESCR_PROPS_HID 0
#define USB_CFG_DESCR_PROPS_HID_REPORT 0
#define USB_CFG_DESCR_PROPS_UNKNOWN 0