1 /* flasher for HomeMatic-devices supporting OTA updates 
   3  * Copyright (c) 2014 Michael Gernoth <michael@gernoth.net> 
   5  * Permission is hereby granted, free of charge, to any person obtaining a copy 
   6  * of this software and associated documentation files (the "Software"), to 
   7  * deal in the Software without restriction, including without limitation the 
   8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
   9  * sell copies of the Software, and to permit persons to whom the Software is 
  10  * furnished to do so, subject to the following conditions: 
  12  * The above copyright notice and this permission notice shall be included in 
  13  * all copies or substantial portions of the Software. 
  15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
  16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
  18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
  19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
  20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
  32 #include <sys/types.h> 
  36 #include <libusb-1.0/libusb.h> 
  47 #define NORMAL_MAX_PAYLOAD      37 
  48 #define LOWER_MAX_PAYLOAD       17 
  57 /* Maximum payloadlen supported by IO */ 
  58 uint32_t max_payloadlen 
= NORMAL_MAX_PAYLOAD
; 
  67         struct hmcfgusb_dev 
*hmcfgusb
; 
  68         struct culfw_dev 
*culfw
; 
  78         enum message_type message_type
; 
  85 static int parse_hmcfgusb(uint8_t *buf
, int buf_len
, void *data
) 
  87         struct recv_data 
*rdata 
= data
; 
  95                             ((buf
[0x11] == ((hmid 
>> 16) & 0xff)) && 
  96                             (buf
[0x12] == ((hmid 
>> 8) & 0xff)) && 
  97                             (buf
[0x13] == (hmid 
& 0xff)))) { 
  98                                 memset(rdata
->message
, 0, sizeof(rdata
->message
)); 
  99                                 memcpy(rdata
->message
, buf 
+ 0x0d, buf
[0x0d] + 1); 
 100                                 rdata
->message_type 
= MESSAGE_TYPE_E
; 
 104                         memset(rdata
->message
, 0, sizeof(rdata
->message
)); 
 105                         memcpy(rdata
->message
, buf 
+ 0x0e, buf
[0x0e] + 1); 
 106                         rdata
->status 
= (buf
[5] << 8) | buf
[6]; 
 107                         rdata
->message_type 
= MESSAGE_TYPE_R
; 
 110                         rdata
->speed 
= buf
[1]; 
 113                         rdata
->version 
= (buf
[11] << 8) | buf
[12]; 
 114                         rdata
->credits 
= buf
[36]; 
 115                         my_hmid 
= (buf
[0x1b] << 16) | (buf
[0x1c] << 8) | buf
[0x1d]; 
 127 static int parse_culfw(uint8_t *buf
, int buf_len
, void *data
) 
 129         struct recv_data 
*rdata 
= data
; 
 132         memset(rdata
, 0, sizeof(struct recv_data
)); 
 142                         while(validate_nibble(buf
[(pos 
* 2) + 1]) && 
 143                               validate_nibble(buf
[(pos 
* 2) + 2]) && 
 144                               (pos 
+ 1 < buf_len
)) { 
 145                                 rdata
->message
[pos
] = ascii_to_nibble(buf
[(pos 
* 2) + 1]) << 4; 
 146                                 rdata
->message
[pos
] |= ascii_to_nibble(buf
[(pos 
* 2) + 2]); 
 150                         if (hmid 
&& (SRC(rdata
->message
) != hmid
)) 
 153                         rdata
->message_type 
= MESSAGE_TYPE_E
; 
 161                                 s 
= ((char*)buf
) + 2; 
 164                                         fprintf(stderr
, "Unknown response from CUL: %s", buf
); 
 169                                 rdata
->version 
= v 
<< 8; 
 174                                         fprintf(stderr
, "Unknown response from CUL: %s", buf
); 
 183                         fprintf(stderr
, "Unknown response from CUL: %s", buf
); 
 191 int send_hm_message(struct ota_dev 
*dev
, struct recv_data 
*rdata
, uint8_t *msg
) 
 193         static uint32_t id 
= 1; 
 199                 case DEVICE_TYPE_HMCFGUSB
: 
 200                         if (gettimeofday(&tv
, NULL
) == -1) { 
 201                                 perror("gettimeofay"); 
 205                         memset(out
, 0, sizeof(out
)); 
 208                         out
[1] = (id 
>> 24) & 0xff; 
 209                         out
[2] = (id 
>> 16) & 0xff; 
 210                         out
[3] = (id 
>> 8) & 0xff; 
 213                         out
[11] = (tv
.tv_usec 
>> 24) & 0xff; 
 214                         out
[12] = (tv
.tv_usec 
>> 16) & 0xff; 
 215                         out
[13] = (tv
.tv_usec 
>> 8) & 0xff; 
 216                         out
[14] = tv
.tv_usec 
& 0xff; 
 218                         memcpy(&out
[0x0f], msg
, msg
[0] + 1); 
 220                         memset(rdata
, 0, sizeof(struct recv_data
)); 
 221                         hmcfgusb_send(dev
->hmcfgusb
, out
, sizeof(out
), 1); 
 224                                 if (rdata
->message_type 
== MESSAGE_TYPE_R
) { 
 225                                         if (((rdata
->status 
& 0xdf) == 0x01) || 
 226                                             ((rdata
->status 
& 0xdf) == 0x02)) { 
 229                                                 if ((rdata
->status 
& 0xff00) == 0x0400) { 
 230                                                         fprintf(stderr
, "\nOut of credits!\n"); 
 231                                                 } else if ((rdata
->status 
& 0xff) == 0x08) { 
 232                                                         fprintf(stderr
, "\nMissing ACK!\n"); 
 233                                                 } else if ((rdata
->status 
& 0xff) == 0x30) { 
 234                                                         fprintf(stderr
, "\nUnknown AES-key requested!\n"); 
 236                                                         fprintf(stderr
, "\nInvalid status: %04x\n", rdata
->status
); 
 242                                 pfd 
= hmcfgusb_poll(dev
->hmcfgusb
, 1000); 
 243                                 if ((pfd 
< 0) && errno
) { 
 244                                         if (errno 
!= ETIMEDOUT
) { 
 245                                                 perror("\n\nhmcfgusb_poll"); 
 251                 case DEVICE_TYPE_CULFW
: 
 256                                 memset(buf
, 0, sizeof(buf
)); 
 259                                 for (i 
= 0; i 
< msg
[0] + 1; i
++) { 
 260                                         buf
[2 + (i 
* 2)] = nibble_to_ascii((msg
[i
] >> 4) & 0xf); 
 261                                         buf
[2 + (i 
* 2) + 1] = nibble_to_ascii(msg
[i
] & 0xf); 
 263                                 buf
[2 + (i 
* 2) ] = '\r'; 
 264                                 buf
[2 + (i 
* 2) + 1] = '\n'; 
 266                                 memset(rdata
, 0, sizeof(struct recv_data
)); 
 267                                 if (culfw_send(dev
->culfw
, buf
, 2 + (i 
* 2) + 1) == 0) { 
 268                                         fprintf(stderr
, "culfw_send failed!\n"); 
 272                                 if (msg
[CTL
] & 0x20) { 
 277                                                 pfd 
= culfw_poll(dev
->culfw
, 200); 
 278                                                 if ((pfd 
< 0) && errno
) { 
 279                                                         if (errno 
!= ETIMEDOUT
) { 
 280                                                                 perror("\n\nculfw_poll"); 
 284                                                 if (rdata
->message_type 
== MESSAGE_TYPE_E
) { 
 290                                                 fprintf(stderr
, "\nMissing ACK!\n"); 
 302 static int switch_speed(struct ota_dev 
*dev
, struct recv_data 
*rdata
, uint8_t speed
) 
 307         printf("Entering %uk-mode\n", speed
); 
 310                 case DEVICE_TYPE_HMCFGUSB
: 
 311                         memset(out
, 0, sizeof(out
)); 
 315                         hmcfgusb_send(dev
->hmcfgusb
, out
, sizeof(out
), 1); 
 319                                 pfd 
= hmcfgusb_poll(dev
->hmcfgusb
, 1000); 
 320                                 if ((pfd 
< 0) && errno
) { 
 321                                         if (errno 
!= ETIMEDOUT
) { 
 322                                                 perror("\n\nhmcfgusb_poll"); 
 326                                 if (rdata
->speed 
== speed
) 
 330                 case DEVICE_TYPE_CULFW
: 
 332                                 return culfw_send(dev
->culfw
, "AR\r\n", 4); 
 334                                 return culfw_send(dev
->culfw
, "Ar\r\n", 4); 
 342 void flash_ota_syntax(char *prog
) 
 344         fprintf(stderr
, "Syntax: %s parameters options\n\n", prog
); 
 345         fprintf(stderr
, "Mandatory parameters:\n"); 
 346         fprintf(stderr
, "\t-f firmware.eq3\tfirmware file to flash\n"); 
 347         fprintf(stderr
, "\t-s SERIAL\tserial of device to flash\n"); 
 348         fprintf(stderr
, "\nOptional parameters:\n"); 
 349         fprintf(stderr
, "\t-c device\tenable CUL-mode with CUL at path \"device\"\n"); 
 350         fprintf(stderr
, "\t-b bps\t\tuse CUL with speed \"bps\" (default: %u)\n", DEFAULT_CUL_BPS
); 
 351         fprintf(stderr
, "\t-l\t\tlower payloadlen (required for devices with little RAM, e.g. CUL v2 and CUL v4)\n"); 
 352         fprintf(stderr
, "\t-h\t\tthis help\n"); 
 353         fprintf(stderr
, "\nOptional parameters for automatically sending device to bootloader\n"); 
 354         fprintf(stderr
, "\t-C\t\tHMID of central (3 hex-bytes, no prefix, e.g. ABCDEF)\n"); 
 355         fprintf(stderr
, "\t-D\t\tHMID of device (3 hex-bytes, no prefix, e.g. 123456)\n"); 
 356         fprintf(stderr
, "\t-K\t\tKNO:KEY AES key-number and key (hex) separated by colon (Fhem hmKey attribute)\n"); 
 357         fprintf(stderr
, "\t\t\tAES is currently not supported when using a culfw-device!\n"); 
 360 int main(int argc
, char **argv
) 
 362         const char twiddlie
[] = { '-', '\\', '|', '/' }; 
 363         const uint8_t cc1101_regs
[] = { 0x10, 0x5B, 0x11, 0xF8, 0x15, 0x47 }; 
 364         char *fw_file 
= NULL
; 
 366         char *culfw_dev 
= NULL
; 
 368         unsigned int bps 
= DEFAULT_CUL_BPS
; 
 370         struct recv_data rdata
; 
 385         printf("HomeMatic OTA flasher version " VERSION 
"\n\n"); 
 387         while((opt 
= getopt(argc
, argv
, "b:c:f:hls:C:D:K:")) != -1) { 
 399                                 printf("Reducing payload-len from %d to %d\n", max_payloadlen
, LOWER_MAX_PAYLOAD
); 
 400                                 max_payloadlen 
= LOWER_MAX_PAYLOAD
; 
 406                                 my_hmid 
= strtoul(optarg
, &endptr
, 16); 
 407                                 if (*endptr 
!= '\0') { 
 408                                         fprintf(stderr
, "Invalid central HMID!\n\n"); 
 409                                         flash_ota_syntax(argv
[0]); 
 414                                 hmid 
= strtoul(optarg
, &endptr
, 16); 
 415                                 if (*endptr 
!= '\0') { 
 416                                         fprintf(stderr
, "Invalid device HMID!\n\n"); 
 417                                         flash_ota_syntax(argv
[0]); 
 422                                 kNo 
= strtoul(optarg
, &endptr
, 10); 
 423                                 if (*endptr 
!= ':') { 
 424                                         fprintf(stderr
, "Invalid key number!\n\n"); 
 425                                         flash_ota_syntax(argv
[0]); 
 429                                 for (cnt 
= 0; cnt 
< 16; cnt
++) { 
 430                                         if (*endptr 
== '\0' || *(endptr
+1) == '\0' || 
 431                                             !validate_nibble(*endptr
) || 
 432                                             !validate_nibble(*(endptr
+1))) { 
 433                                                 fprintf(stderr
, "Invalid key!\n\n"); 
 434                                                 flash_ota_syntax(argv
[0]); 
 437                                         key
[cnt
] = ascii_to_nibble(*endptr
) << 4 | ascii_to_nibble(*(endptr
+1)); 
 445                                 flash_ota_syntax(argv
[0]); 
 452         if (!fw_file 
|| !serial
) { 
 453                 flash_ota_syntax(argv
[0]); 
 457         fw 
= firmware_read_firmware(fw_file
, debug
); 
 461         memset(&rdata
, 0, sizeof(rdata
)); 
 462         memset(&dev
, 0, sizeof(struct ota_dev
)); 
 466                         fprintf(stderr
, "\nAES currently not supported with culfw-device!\n"); 
 467                         flash_ota_syntax(argv
[0]); 
 471                 printf("Opening culfw-device at path %s with speed %u\n", culfw_dev
, bps
); 
 472                 dev
.culfw 
= culfw_init(culfw_dev
, bps
, parse_culfw
, &rdata
); 
 474                         fprintf(stderr
, "Can't initialize CUL at %s with rate %u\n", culfw_dev
, bps
); 
 477                 dev
.type 
= DEVICE_TYPE_CULFW
; 
 479                 printf("Requesting firmware version\n"); 
 480                 culfw_send(dev
.culfw
, "\r\n", 2); 
 481                 culfw_flush(dev
.culfw
); 
 484                         culfw_send(dev
.culfw
, "V\r\n", 3); 
 487                         pfd 
= culfw_poll(dev
.culfw
, 1000); 
 488                         if ((pfd 
< 0) && errno
) { 
 489                                 if (errno 
!= ETIMEDOUT
) { 
 490                                         perror("\n\nhmcfgusb_poll"); 
 498                 printf("culfw-device firmware version: %u.%02u\n",  
 499                         (rdata
.version 
>> 8) & 0xff, 
 500                         rdata
.version 
& 0xff); 
 502                 if (rdata
.version 
< 0x013a) { 
 503                         fprintf(stderr
, "\nThis version does _not_ support firmware upgrade mode, you need at least 1.58!\n"); 
 507                 uint32_t new_hmid 
= my_hmid
; 
 509                 hmcfgusb_set_debug(debug
); 
 511                 dev
.hmcfgusb 
= hmcfgusb_init(parse_hmcfgusb
, &rdata
); 
 513                         fprintf(stderr
, "Can't initialize HM-CFG-USB\n"); 
 516                 dev
.type 
= DEVICE_TYPE_HMCFGUSB
; 
 518                 memset(out
, 0, sizeof(out
)); 
 520                 hmcfgusb_send(dev
.hmcfgusb
, out
, sizeof(out
), 1); 
 524                         pfd 
= hmcfgusb_poll(dev
.hmcfgusb
, 1000); 
 525                         if ((pfd 
< 0) && errno
) { 
 526                                 if (errno 
!= ETIMEDOUT
) { 
 527                                         perror("\n\nhmcfgusb_poll"); 
 535                 if (rdata
.version 
< 0x3c7) { 
 536                         fprintf(stderr
, "HM-CFG-USB firmware too low: %u < 967\n", rdata
.version
); 
 540                 printf("HM-CFG-USB firmware version: %u, used credits: %u%%\n", rdata
.version
, rdata
.credits
); 
 542                 if (rdata
.credits 
>= 40) { 
 543                         printf("\nRebooting HM-CFG-USB to avoid running out of credits\n\n"); 
 545                         if (!dev
.hmcfgusb
->bootloader
) { 
 546                                 printf("HM-CFG-USB not in bootloader mode, entering bootloader.\n"); 
 547                                 printf("Waiting for device to reappear...\n"); 
 551                                                 if (!dev
.hmcfgusb
->bootloader
) 
 552                                                         hmcfgusb_enter_bootloader(dev
.hmcfgusb
); 
 553                                                 hmcfgusb_close(dev
.hmcfgusb
); 
 556                                 } while (((dev
.hmcfgusb 
= hmcfgusb_init(parse_hmcfgusb
, &rdata
)) == NULL
) || (!dev
.hmcfgusb
->bootloader
)); 
 559                         if (dev
.hmcfgusb
->bootloader
) { 
 560                                 printf("HM-CFG-USB in bootloader mode, rebooting\n"); 
 564                                                 if (dev
.hmcfgusb
->bootloader
) 
 565                                                         hmcfgusb_leave_bootloader(dev
.hmcfgusb
); 
 566                                                 hmcfgusb_close(dev
.hmcfgusb
); 
 569                                 } while (((dev
.hmcfgusb 
= hmcfgusb_init(parse_hmcfgusb
, &rdata
)) == NULL
) || (dev
.hmcfgusb
->bootloader
)); 
 573                 printf("\n\nHM-CFG-USB opened\n\n"); 
 575                 if (new_hmid 
&& (my_hmid 
!= new_hmid
)) { 
 576                         printf("Changing hmid from %06x to %06x\n", my_hmid
, new_hmid
); 
 578                         memset(out
, 0, sizeof(out
)); 
 580                         out
[1] = (new_hmid 
>> 16) & 0xff; 
 581                         out
[2] = (new_hmid 
>> 8) & 0xff; 
 582                         out
[3] = new_hmid 
& 0xff; 
 584                         hmcfgusb_send(dev
.hmcfgusb
, out
, sizeof(out
), 1); 
 590                         printf("Setting AES-key\n"); 
 592                         memset(out
, 0, sizeof(out
)); 
 596                         out
[3] = sizeof(key
); 
 597                         memcpy(&(out
[4]), key
, sizeof(key
)); 
 598                         hmcfgusb_send(dev
.hmcfgusb
, out
, sizeof(out
), 1); 
 600                         memset(out
, 0, sizeof(out
)); 
 605                         hmcfgusb_send(dev
.hmcfgusb
, out
, sizeof(out
), 1); 
 607                         memset(out
, 0, sizeof(out
)); 
 612                         hmcfgusb_send(dev
.hmcfgusb
, out
, sizeof(out
), 1); 
 616         if (!switch_speed(&dev
, &rdata
, 10)) { 
 617                 fprintf(stderr
, "Can't switch speed!\n"); 
 621         if (hmid 
&& my_hmid
) { 
 622                 printf("Sending device with hmid %06x to bootloader\n", hmid
); 
 623                 out
[MSGID
] = msgid
++; 
 626                 SET_SRC(out
, my_hmid
); 
 629                 SET_LEN_FROM_PAYLOADLEN(out
, 1); 
 633                         if (send_hm_message(&dev
, &rdata
, out
)) { 
 638                         printf("Failed to send device to bootloader, please enter bootloader manually.\n"); 
 642         printf("Waiting for device with serial %s\n", serial
); 
 647                         case DEVICE_TYPE_CULFW
: 
 648                                 pfd 
= culfw_poll(dev
.culfw
, 1000); 
 650                         case DEVICE_TYPE_HMCFGUSB
: 
 652                                 pfd 
= hmcfgusb_poll(dev
.hmcfgusb
, 1000); 
 656                 if ((pfd 
< 0) && errno
) { 
 657                         if (errno 
!= ETIMEDOUT
) { 
 663                 if ((rdata
.message
[LEN
] == 0x14) && /* Length */ 
 664                     (rdata
.message
[MSGID
] == 0x00) && /* Message ID */ 
 665                     (rdata
.message
[CTL
] == 0x00) && /* Control Byte */ 
 666                     (rdata
.message
[TYPE
] == 0x10) && /* Messagte type: Information */ 
 667                     (DST(rdata
.message
) == 0x000000) && /* Broadcast */ 
 668                     (rdata
.message
[PAYLOAD
] == 0x00)) { /* FUP? */ 
 669                         if (!strncmp((char*)&(rdata
.message
[0x0b]), serial
, 10)) { 
 670                                 hmid 
= SRC(rdata
.message
); 
 676         printf("Device with serial %s (hmid: %06x) entered firmware-update-mode\n", serial
, hmid
); 
 678         if (dev
.type 
== DEVICE_TYPE_HMCFGUSB
) { 
 679                 printf("Adding HMID\n"); 
 681                 memset(out
, 0, sizeof(out
)); 
 683                 out
[1] = (hmid 
>> 16) & 0xff; 
 684                 out
[2] = (hmid 
>> 8) & 0xff; 
 685                 out
[3] = hmid 
& 0xff; 
 687                 hmcfgusb_send(dev
.hmcfgusb
, out
, sizeof(out
), 1); 
 692                 printf("Initiating remote switch to 100k\n"); 
 694                 memset(out
, 0, sizeof(out
)); 
 696                 out
[MSGID
] = msgid
++; 
 699                 SET_SRC(out
, my_hmid
); 
 702                 memcpy(&out
[PAYLOAD
], cc1101_regs
, sizeof(cc1101_regs
)); 
 703                 SET_LEN_FROM_PAYLOADLEN(out
, sizeof(cc1101_regs
)); 
 705                 if (!send_hm_message(&dev
, &rdata
, out
)) { 
 709                 if (!switch_speed(&dev
, &rdata
, 100)) { 
 710                         fprintf(stderr
, "Can't switch speed!\n"); 
 714                 printf("Has the device switched?\n"); 
 716                 memset(out
, 0, sizeof(out
)); 
 718                 out
[MSGID
] = msgid
++; 
 721                 SET_SRC(out
, my_hmid
); 
 724                 memcpy(&out
[PAYLOAD
], cc1101_regs
, sizeof(cc1101_regs
)); 
 725                 SET_LEN_FROM_PAYLOADLEN(out
, sizeof(cc1101_regs
)); 
 729                         if (send_hm_message(&dev
, &rdata
, out
)) { 
 730                                 /* A0A02000221B9AD00000000 */ 
 739                         if (!switch_speed(&dev
, &rdata
, 10)) { 
 740                                 fprintf(stderr
, "Can't switch speed!\n"); 
 744         } while ((!switched
) && (switchcnt
--)); 
 747                 fprintf(stderr
, "Too many errors, giving up!\n"); 
 753         printf("Flashing %d blocks", fw
->fw_blocks
); 
 757                 printf(": %04u/%04u %c", 0, fw
->fw_blocks
, twiddlie
[0]); 
 761         for (block 
= 0; block 
< fw
->fw_blocks
; block
++) { 
 764                 len 
= fw
->fw
[block
][2] << 8; 
 765                 len 
|= fw
->fw
[block
][3]; 
 767                 pos 
= &(fw
->fw
[block
][2]); 
 769                 len 
+= 2; /* length */ 
 772                         hexdump(pos
, len
, "F> "); 
 777                         int payloadlen 
= max_payloadlen 
- 2; 
 781                                 payloadlen 
= max_payloadlen
; 
 785                         if ((len 
- (pos 
- &(fw
->fw
[block
][2]))) < payloadlen
) 
 786                                 payloadlen 
= (len 
- (pos 
- &(fw
->fw
[block
][2]))); 
 788                         if (((pos 
+ payloadlen
) - &(fw
->fw
[block
][2])) == len
) 
 791                         memset(&rdata
, 0, sizeof(rdata
)); 
 793                         memset(out
, 0, sizeof(out
)); 
 799                         SET_SRC(out
, my_hmid
); 
 802                         memcpy(&out
[PAYLOAD
], pos
, payloadlen
); 
 803                         SET_LEN_FROM_PAYLOADLEN(out
, payloadlen
); 
 805                         if (send_hm_message(&dev
, &rdata
, out
)) { 
 808                                 pos 
= &(fw
->fw
[block
][2]); 
 810                                 if (cnt 
== MAX_RETRIES
) { 
 811                                         fprintf(stderr
, "\nToo many errors, giving up!\n"); 
 814                                         printf("Flashing %d blocks: %04u/%04u %c", fw
->fw_blocks
, block 
+ 1, fw
->fw_blocks
, twiddlie
[msgnum 
% sizeof(twiddlie
)]); 
 821                                 printf("\b\b\b\b\b\b\b\b\b\b\b%04u/%04u %c", 
 822                                         block 
+ 1, fw
->fw_blocks
, twiddlie
[msgnum 
% sizeof(twiddlie
)]); 
 825                 } while((pos 
- &(fw
->fw
[block
][2])) < len
); 
 833         if (!switch_speed(&dev
, &rdata
, 10)) { 
 834                 fprintf(stderr
, "Can't switch speed!\n"); 
 838         printf("Waiting for device to reboot\n"); 
 844                         case DEVICE_TYPE_CULFW
: 
 845                                 pfd 
= culfw_poll(dev
.culfw
, 1000); 
 847                         case DEVICE_TYPE_HMCFGUSB
: 
 849                                 pfd 
= hmcfgusb_poll(dev
.hmcfgusb
, 1000); 
 852                 if ((pfd 
< 0) && errno
) { 
 853                         if (errno 
!= ETIMEDOUT
) { 
 858                 if (rdata
.message_type 
== MESSAGE_TYPE_E
) { 
 863         if (rdata
.message_type 
== MESSAGE_TYPE_E
) { 
 864                 printf("Device rebooted\n"); 
 868                 case DEVICE_TYPE_HMCFGUSB
: 
 869                         hmcfgusb_close(dev
.hmcfgusb
); 
 872                 case DEVICE_TYPE_CULFW
: 
 873                         culfw_close(dev
.culfw
);