signed RemoteHosts (struct plc * plc) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_sw_ver_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; } * request = (struct vs_sw_ver_request *) (message); struct __packed vs_sw_ver_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint32_t NUMDEVICES; struct __packed { uint8_t MACADDRESS [ETHER_ADDR_LEN]; uint8_t ENUMID; } DEVICE [1]; } * confirm = (struct vs_sw_ver_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (plc, "Request Enumeration ID Table"); memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_EM_ID_TABLE | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } while (ReadMME (plc, 0, (VS_EM_ID_TABLE | MMTYPE_CNF)) > 0) { unsigned count = LE32TOH (confirm->NUMDEVICES); if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); continue; } while (count--) { hexout (confirm->DEVICE [count].MACADDRESS, ETHER_ADDR_LEN, ':', count? ' ': '\n', stdout); } } return (0); }
static signed DefaultVLANIDs (struct plc * plc, struct item list [], unsigned items) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_forward_config_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t RESERVED1; uint8_t MREQUEST; uint8_t MVERSION; uint32_t RESERVED2; uint16_t VLANID; uint16_t RESERVED3; } * request = (struct vs_forward_config_request *) (message); struct __packed vs_forward_config_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t RESERVED1; uint8_t RESULTCODE; uint8_t OPERATION; uint8_t MVERSION; uint32_t RESERVED2; } * confirm = (struct vs_forward_config_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_FORWARD_CONFIG | MMTYPE_REQ)); request->MREQUEST = PLCFWD_SET; request->MVERSION = PLCFWD_VER; request->VLANID = HTOLE16 (list [0].VLANID [0]); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } while (ReadMME (plc, 0, (VS_FORWARD_CONFIG | MMTYPE_CNF)) > 0) { if (confirm->RESULTCODE) { Failure (plc, PLC_WONTDOIT); continue; } } return (0); }
static signed mod_conn (struct plc * plc, uint8_t TYPE, uint16_t CID) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_mod_conn_req { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint32_t REQ_ID; uint32_t RSVD; uint16_t CID; uint8_t MOD_CTRL; } * request = (struct vs_mod_conn_req *)(message); struct __packed vs_mod_conn_cnf { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint32_t REQ_ID; uint8_t MSTATUS; uint16_t ERR_REC_CODE; uint32_t RSVD; uint16_t CID; } * confirm = (struct vs_mod_conn_cnf *)(message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (plc, "COQOS modify connection"); memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, HOMEPLUG_MTYPE); QualcommHeader (&request->qualcomm, 0, (VS_MOD_CONN | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); request->MOD_CTRL = TYPE; request->CID = CID; if (SendMME (plc) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTSEND); return (-1); } while (ReadMME (plc, 0, (VS_MOD_CONN | MMTYPE_CNF)) > 0) { if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } Confirm (plc, "%s connection %04X", (TYPE == ACTION_SPND)? "Suspended": "Resumed", CID); } return (0); }
signed rel_conn (struct plc * plc, uint16_t CID) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_rel_conn_req { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint32_t REQ_ID; uint32_t RSVD; uint16_t CID; } * request = (struct vs_rel_conn_req *)(message); struct __packed vs_rel_conn_cnf { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint32_t REQ_ID; uint8_t MSTATUS; uint16_t ERR_REC_CODE; uint32_t RSVD; } * confirm = (struct vs_rel_conn_cnf *)(message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (plc, "Release COQOS connection"); memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_CONN_REL | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); request->CID = CID; if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } while (ReadMME (plc, 0, (VS_CONN_REL | MMTYPE_CNF)) > 0) { if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } Confirm (plc, "Released %04X", CID); } return (0); }
signed Flash (struct int6k * int6k) { struct channel * channel = (struct channel *)(int6k->channel); struct message * message = (struct message *)(int6k->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_mod_nvm_request { struct header_eth ethernet; struct header_int intellon; uint8_t MODULEID; } * request = (struct vs_mod_nvm_request *) (message); struct __packed vs_mod_nvm_confirm { struct header_eth ethernet; struct header_int intellon; uint8_t MSTATUS; uint8_t MODULEID; } * confirm = (struct vs_mod_nvm_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (int6k, "Flash NVRAM"); memset (message, 0, sizeof (struct message)); EthernetHeader (&message->ethernet, channel->peer, channel->host); IntellonHeader (&message->intellon, (VS_MOD_NVM | MMTYPE_REQ)); int6k->packetsize = ETHER_MIN_LEN; request->MODULEID = int6k->modulecode; if (SendMME (int6k) <= 0) { error ((int6k->flags & INT6K_BAILOUT), ECANCELED, INT6K_CANTSEND); return (-1); } if (ReadMME (int6k, (VS_MOD_NVM | MMTYPE_CNF)) <= 0) { error ((int6k->flags & INT6K_BAILOUT), ECANCELED, INT6K_CANTREAD); return (-1); } if (confirm->MSTATUS) { Failure (int6k, INT6K_WONTDOIT); return (-1); } Confirm (int6k, "Flashing ..."); return (0); }
signed Classification (struct plc * plc, struct MMERule * rule) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_classification_request { struct ethernet_std ethernet; struct qualcomm_std qualcomm; struct MMERule rule; } * request = (struct vs_classification_request *)(message); struct __packed vs_classification_confirm { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint8_t MSTATUS; } * confirm = (struct vs_classification_confirm *)(message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (plc, "Set Classification Rules"); memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_CLASSIFICATION | MMTYPE_REQ)); plc->packetsize = sizeof (struct vs_classification_request); memcpy (&request->rule, rule, sizeof (request->rule)); if (SendMME (plc) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_CLASSIFICATION | MMTYPE_CNF)) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTREAD); return (-1); } if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } Confirm (plc, "Setting ..."); return (0); }
signed FlashNVM (struct plc * plc) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_mod_nvm_request { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint8_t MODULEID; } * request = (struct vs_mod_nvm_request *) (message); struct __packed vs_mod_nvm_confirm { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint8_t MSTATUS; uint8_t MODULEID; } * confirm = (struct vs_mod_nvm_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (plc, "Flash device"); memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_MOD_NVM | MMTYPE_REQ)); request->MODULEID = plc->module; plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); if (SendMME (plc) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_MOD_NVM | MMTYPE_CNF)) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTREAD); return (-1); } if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } return (0); }
signed HostActionIndicate (struct plc * plc) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_host_action_ind { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MACTION; uint8_t MAJOR_VERSION; uint8_t MINOR_VERSION; } * indicate = (struct vs_host_action_ind *) (message); struct __packed vs_host_action_rsp { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; } * response = (struct vs_host_action_rsp *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (plc, "Start Host Action"); memset (message, 0, sizeof (* message)); EthernetHeader (&indicate->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&indicate->qualcomm, 0, (VS_HOST_ACTION | MMTYPE_IND)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); indicate->MACTION = plc->action; if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } while (ReadMME (plc, 0, (VS_HOST_ACTION | MMTYPE_RSP)) > 0) { if (response->MSTATUS) { Failure (plc, PLC_WONTDOIT); continue; } Confirm (plc, "Start."); } return (0); }
signed VersionInfo (struct int6k * int6k) { extern const char * chipset [CHIPSETS+1]; struct channel * channel = (struct channel *)(int6k->channel); struct message * message = (struct message *)(int6k->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_sw_ver_confirm { struct header_eth ethernet; struct header_int intellon; uint8_t MSTATUS; uint8_t MDEVICEID; uint8_t MVERLENGTH; char MVERSION [INT6K_VERSTRING]; uint8_t UPGRADEABLE; uint32_t MCOOKIE; } * confirm = (struct vs_sw_ver_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (int6k, "Request Version Information"); memset (message, 0, sizeof (struct message)); EthernetHeader (&message->ethernet, channel->peer, channel->host); IntellonHeader (&message->intellon, (VS_SW_VER | MMTYPE_REQ)); int6k->packetsize = ETHER_MIN_LEN; if (SendMME (int6k) <= 0) { error ((int6k->flags & INT6K_BAILOUT), ECANCELED, INT6K_CANTSEND); return (-1); } while (ReadMME (int6k, (VS_SW_VER | MMTYPE_CNF)) > 0) { if (confirm->MSTATUS) { Failure (int6k, INT6K_WONTDOIT); continue; } if (confirm->MDEVICEID > CHIPSETS) { confirm->MDEVICEID = 0x00; } Display (int6k, "%s %s", chipset [confirm->MDEVICEID], confirm->MVERSION); } return (0); }
signed VersionInfo1 (struct plc * plc) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_sw_ver_request { struct ethernet_std ethernet; struct qualcomm_std qualcomm; } * request = (struct vs_sw_ver_request *) (message); struct __packed vs_sw_ver_confirm { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint8_t MSTATUS; uint8_t MDEVICEID; uint8_t MVERLENGTH; char MVERSION [PLC_VERSION_STRING]; } * confirm = (struct vs_sw_ver_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (plc, "Request Version Information"); memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_SW_VER | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); if (SendMME (plc) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTSEND); return (-1); } while (ReadMME (plc, 0, (VS_SW_VER | MMTYPE_CNF)) > 0) { if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); continue; } chipset (confirm); Display (plc, "%s %s", chipsetname (confirm->MDEVICEID), confirm->MVERSION); } return (0); }
signed Antiphon (struct plc * plc, byte source [], byte target []) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_fr_lbk_request { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint8_t DURATION; uint8_t RESERVED; uint16_t LENGTH; uint8_t PACKET [1038]; } * request = (struct vs_fr_lbk_request *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif if (_allclr (plc->flags, PLC_SILENCE)) { char sourcename [ETHER_ADDR_LEN * 3]; char targetname [ETHER_ADDR_LEN * 3]; hexdecode (source, ETHER_ADDR_LEN, sourcename, sizeof (sourcename)); hexdecode (target, ETHER_ADDR_LEN, targetname, sizeof (targetname)); fprintf (stderr, "%s %s %s\n", channel->ifname, sourcename, targetname); } memset (message, 0, sizeof (* message)); EthernetHeader (&message->ethernet, source, channel->host, HOMEPLUG_MTYPE); QualcommHeader (&message->qualcomm, 0, (VS_FR_LBK | MMTYPE_REQ)); request->DURATION = plc->timer; request->LENGTH = HTOLE16 (sizeof (request->PACKET)); memset (request->PACKET, 0xA5, sizeof (request->PACKET)); EthernetHeader (request->PACKET, target, source, ETHERTYPE_IP); plc->packetsize = sizeof (* request); if (SendMME (plc) <= 0) { error (1, errno, CHANNEL_CANTSEND); } if (ReadMME (plc, 0, (VS_FR_LBK | MMTYPE_CNF)) <= 0) { error (1, errno, CHANNEL_CANTREAD); } sleep (plc->timer); return (0); }
signed FactoryDefaults (struct plc * plc) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_fac_defaults_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; } * request = (struct vs_fac_defaults_request *) (message); struct __packed vs_fac_defaults_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; } * confirm = (struct vs_fac_defaults_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (plc, "Restore Factory Defaults"); memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_FAC_DEFAULTS | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } while (ReadMME (plc, 0, (VS_FAC_DEFAULTS | MMTYPE_CNF)) > 0) { if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); continue; } Confirm (plc, "Restoring ..."); } return (0); }
signed PLCNetworkInfo (struct plc * plc) { signed status; struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_sw_ver_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint8_t MDEVICEID; uint8_t MVERLENGTH; char MVERSION [PLC_VERSION_STRING]; } * request = (struct vs_sw_ver_request *) (message); struct __packed vs_sw_ver_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint8_t MDEVICEID; uint8_t MVERLENGTH; char MVERSION [PLC_VERSION_STRING]; } * confirm = (struct vs_sw_ver_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_SW_VER | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_SW_VER | MMTYPE_CNF)) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD); return (-1); } if (confirm->MSTATUS) { Failure (plc, "Device will not start"); return (-1); } chipset (confirm); if ((plc->hardwareID = confirm->MDEVICEID) < CHIPSET_AR7400) { status = NetInfo1 (plc); } else { status = NetInfo2 (plc); } return (status); }
signed EmulateHost (struct plc * plc) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); static char const * actions [] = { "start device", "store firmware", "store parameters", "update host", "config memory", "restore defaults", "unknown" }; #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_host_action_ind { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MACTION; uint8_t MAJOR_VERSION; uint8_t MINOR_VERSION; } * indicate = (struct vs_host_action_ind *) (message); #if 0 struct __packed vs_host_action_rsp { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; } * response = (struct vs_host_action_rsp *) (message); #endif #ifndef __GNUC__ #pragma pack (pop) #endif struct nvm_header1 nvm_header; struct pib_header pib_header; uint32_t offset; char const * PIB = plc->PIB.name; char const * NVM = plc->NVM.name; signed timer = channel->timeout; signed status = 0; Request (plc, "Waiting for Host Action"); while (1) { channel->timeout = plc->timer; status = ReadMME (plc, 0, (VS_HOST_ACTION | MMTYPE_IND)); channel->timeout = timer; if (status < 0) { break; } if (status > 0) { printf ("\n"); if (indicate->MACTION < (sizeof (actions) / sizeof (char const *))) { Confirm (plc, "Host Action Request is (%d) %s.", indicate->MACTION, actions [indicate->MACTION]); } else { error (0, ENOTSUP, "Host Action 0x%0X", indicate->MACTION); continue; } memcpy (channel->peer, indicate->ethernet.OSA, sizeof (channel->peer)); channel->timeout = timer; if (indicate->MACTION == 0x00) { unsigned module = 0; char firmware [PLC_VERSION_STRING]; if (HostActionResponse (plc)) { return (-1); } if (lseek (plc->PIB.file, 0, SEEK_SET)) { error (1, errno, FILE_CANTHOME, plc->PIB.name); } if (read (plc->PIB.file, &pib_header, sizeof (pib_header)) != sizeof (pib_header)) { error (1, errno, FILE_CANTREAD, plc->PIB.name); } if (lseek (plc->PIB.file, 0, SEEK_SET)) { error (1, errno, FILE_CANTHOME, plc->PIB.name); } if (BE16TOH (*(uint16_t *)(&pib_header)) < 0x0305) { offset = LEGACY_PIBOFFSET; } else if (BE16TOH (*(uint16_t *)(&pib_header)) < 0x0500) { offset = INT6x00_PIBOFFSET; } else { offset = AR7x00_PIBOFFSET; } if (WriteMEM (plc, &plc->PIB, 0, offset, LE16TOH (pib_header.PIBLENGTH))) { return (-1); } if (lseek (plc->NVM.file, 0, SEEK_SET)) { error (1, errno, FILE_CANTHOME, plc->NVM.name); } if (read (plc->NVM.file, &nvm_header, sizeof (nvm_header)) != sizeof (nvm_header)) { error (1, errno, FILE_CANTREAD, plc->NVM.name); } while (nvm_header.NEXTHEADER) { lseek (plc->NVM.file, LE32TOH (nvm_header.NEXTHEADER), SEEK_SET); if (read (plc->NVM.file, &nvm_header, sizeof (nvm_header)) != sizeof (nvm_header)) { error (1, errno, FILE_CANTREAD, plc->NVM.name); } module++; } if (WriteFirmware1 (plc, module, &nvm_header)) { return (-1); } if (StartFirmware1 (plc, module, &nvm_header)) { return (-1); } if (WaitForStart (plc, firmware, sizeof (firmware))) { return (-1); } if (_anyset (plc->flags, PLC_FLASH_DEVICE)) { if (WriteNVM (plc)) { return (-1); } if (WritePIB (plc)) { return (-1); } if (FlashNVM (plc)) { return (-1); } } continue; } if (indicate->MACTION == 0x01) { if (HostActionResponse (plc)) { return (-1); } close (plc->NVM.file); if (ReadFirmware1 (plc)) { return (-1); } if ((plc->NVM.file = open (plc->NVM.name = plc->nvm.name, O_BINARY|O_RDONLY)) == -1) { error (1, errno, "%s", plc->NVM.name); } if (ResetDevice (plc)) { return (-1); } continue; } if (indicate->MACTION == 0x02) { if (HostActionResponse (plc)) { return (-1); } close (plc->PIB.file); if (ReadParameters1 (plc)) { return (-1); } if ((plc->PIB.file = open (plc->PIB.name = plc->pib.name, O_BINARY|O_RDONLY)) == -1) { error (1, errno, "%s", plc->PIB.name); } if (ResetDevice (plc)) { return (-1); } continue; } if (indicate->MACTION == 0x03) { if (HostActionResponse (plc)) { return (-1); } close (plc->NVM.file); if (ReadFirmware1 (plc)) { return (-1); } if ((plc->NVM.file = open (plc->NVM.name = plc->nvm.name, O_BINARY|O_RDONLY)) == -1) { error (1, errno, "%s", plc->NVM.name); } close (plc->PIB.file); if (ReadParameters1 (plc)) { return (-1); } if ((plc->PIB.file = open (plc->PIB.name = plc->pib.name, O_BINARY|O_RDONLY)) == -1) { error (1, errno, "%s", plc->PIB.name); } if (ResetDevice (plc)) { return (-1); } continue; } if (indicate->MACTION == 0x04) { #if 0 /* * Due to an omission in the INT6300 BootLoader, responding to this VS_HOST_ACTION * indication will suppress subsequent VS_HOST_ACTION messages and the device will * not request firmware and parameters; this may be corrected on the INT6400; */ if (HostActionResponse (plc)) { return (-1); } #endif if (WriteCFG (plc)) { return (-1); } /* * At this point, one could download firmware and parameters without waiting for * further requests from the device; however, we elect to wait for them since it * is 'good form'; a device should send code 0x00 within 10 seconds of this one; */ continue; } if (indicate->MACTION == 0x05) { if (HostActionResponse (plc)) { return (-1); } close (plc->NVM.file); if ((plc->NVM.file = open (plc->NVM.name = NVM, O_BINARY|O_RDONLY)) == -1) { error (1, errno, "%s", plc->NVM.name); } close (plc->PIB.file); if ((plc->PIB.file = open (plc->PIB.name = PIB, O_BINARY|O_RDONLY)) == -1) { error (1, errno, "%s", plc->PIB.name); } if (ResetDevice (plc)) { return (-1); } continue; } error (0, ENOSYS, "Host Action 0x%0X", indicate->MACTION); } } return (0); }
signed MDUTrafficStats (struct plc * plc, uint8_t command, uint8_t session, uint8_t slave) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_mdu_station_stats_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t COMMAND; uint8_t SESSION; uint32_t SLAVE_BITMAP [8]; } * request = (struct vs_mdu_station_stats_request *) (message); struct __packed vs_mdu_traffic_master_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t COMMAND; uint8_t SESSION; uint16_t RESERVED; uint8_t NUM_SLAVES; uint8_t NUM_SLAVES_LEFT; uint16_t STATS_LEN; struct station_stats STATS [1]; } * master_confirm = (struct vs_mdu_traffic_master_confirm *) (message); struct __packed vs_mdu_traffic_slave_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t COMMAND; uint8_t SESSION; uint16_t STATS_LEN; struct station_stats STATS [1]; } * slave_confirm = (struct vs_mdu_traffic_slave_confirm *) (message); #if 1 struct __packed vs_eth_hardware_stats_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t COMMAND; uint8_t SESSION; uint8_t CHIPTYPE; uint8_t STATUS; uint16_t STATS_LEN; struct ethernet_stats STATS [1]; } * ether_confirm = (struct vs_eth_hardware_stats_confirm *) (message); #endif #ifndef __GNUC__ #pragma pack (pop) #endif Request (plc, "Request MDU Traffic Statistics (1)"); memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_MDU_TRAFFIC_STATS | MMTYPE_REQ)); request->COMMAND = command; request->SESSION = session; set32bitmap (request->SLAVE_BITMAP, slave); plc->packetsize = sizeof (* request); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } while (ReadMME (plc, 0, (VS_MDU_TRAFFIC_STATS | MMTYPE_CNF)) > 0) { if ((request->COMMAND > 0x00) && (request->COMMAND < 0x0020)) { struct station_stats * stats; unsigned count; if (_anyset (request->COMMAND, MASTER_TX_RX | SLAVE_TX_RX)) { stats = master_confirm->STATS; count = LE16TOH (master_confirm->STATS_LEN); } else { stats = slave_confirm->STATS; count = LE16TOH (slave_confirm->STATS_LEN); } while (count >= sizeof (struct station_stats)) { StationStats (plc, stats++); count -= sizeof (struct station_stats); } continue; } if ((request->COMMAND >= 0x20) && (request->COMMAND < 0x24)) { EthernetStats (plc, ether_confirm->STATS); continue; } if ((request->COMMAND >= 0x24) && (request->COMMAND < 0x28)) { EthernetStats (plc, ether_confirm->STATS); continue; } if ((request->COMMAND >= 0x28) && (request->COMMAND < 0x32)) { EthernetStats (plc, ether_confirm->STATS); continue; } } return (0); }
signed WriteFirmware1 (struct plc * plc, unsigned module, const struct nvm_header1 * nvm_header) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_wr_mem_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint32_t MOFFSET; uint32_t MLENGTH; uint8_t BUFFER [PLC_RECORD_SIZE]; } * request = (struct vs_wr_mem_request *) (message); struct __packed vs_wr_mem_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint32_t MOFFSET; uint32_t MLENGTH; } * confirm = (struct vs_wr_mem_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif uint32_t length = PLC_RECORD_SIZE; uint32_t offset = LE32TOH (nvm_header->IMAGEADDRESS); uint32_t extent = LE32TOH (nvm_header->IMAGELENGTH); Request (plc, "Write %s (%d) (%08X:%d)", plc->NVM.name, module, offset, extent); while (extent) { memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_WR_MEM | MMTYPE_REQ)); if (length > extent) { length = extent; } if (read (plc->NVM.file, request->BUFFER, length) != (signed)(length)) { error (1, errno, FILE_CANTREAD, plc->NVM.name); } request->MLENGTH = HTOLE32 (length); request->MOFFSET = HTOLE32 (offset); plc->packetsize = sizeof (* request); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_WR_MEM | MMTYPE_CNF)) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD); return (-1); } if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } if (LE32TOH (confirm->MLENGTH) != length) { error (PLC_EXIT (plc), 0, PLC_ERR_LENGTH); return (-1); } if (LE32TOH (confirm->MOFFSET) != offset) { error (PLC_EXIT (plc), 0, PLC_ERR_OFFSET); return (-1); } offset += length; extent -= length; } return (0); }
signed WaitForStart (struct plc * plc, char string [], size_t length) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); struct timeval ts; struct timeval tc; unsigned timer = 0; #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_sw_ver_request { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint8_t MSTATUS; uint8_t MDEVICEID; uint8_t MVERLENGTH; char MVERSION [PLC_VERSION_STRING]; } * request = (struct vs_sw_ver_request *) (message); struct __packed vs_sw_ver_confirm { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint8_t MSTATUS; uint8_t MDEVICEID; uint8_t MVERLENGTH; char MVERSION [PLC_VERSION_STRING]; } * confirm = (struct vs_sw_ver_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (plc, "Allow %d seconds for Start", plc->timer); if (gettimeofday (&ts, NULL) == -1) { error (1, errno, CANT_START_TIMER); } for (timer = 0; timer < plc->timer; timer = SECONDS (ts, tc)) { memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_SW_VER | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); if (SendMME (plc) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_SW_VER | MMTYPE_CNF)) < 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTREAD); return (-1); } if (gettimeofday (&tc, NULL) == -1) { error (1, errno, CANT_RESET_TIMER); } if (plc->packetsize) { if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } if (_allset (plc->flags, (PLC_WAITFORSTART | PLC_ANALYSE))) { Confirm (plc, "Waited %d seconds for Start", timer); } strncpy (string, confirm->MVERSION, length); return (0); } } if (_allset (plc->flags, (PLC_WAITFORSTART | PLC_ANALYSE))) { Confirm (plc, "Waited %d seconds for Start", timer); } return (-1); }
signed SetNMK (struct plc * plc) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_set_key_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t EKS; uint8_t NMK [HPAVKEY_NMK_LEN]; uint8_t PEKS; uint8_t RDA [ETHER_ADDR_LEN]; uint8_t DAK [HPAVKEY_DAK_LEN]; } * request = (struct vs_set_key_request *) (message); struct __packed vs_set_key_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; } * confirm = (struct vs_set_key_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_SET_KEY | MMTYPE_REQ)); plc->packetsize = sizeof (struct vs_set_key_request); request->EKS = 0x01; memcpy (request->NMK, plc->NMK, sizeof (request->NMK)); if (_anyset (plc->flags, PLC_SETREMOTEKEY)) { Request (plc, "Set Remote Network Membership Key"); memcpy (request->RDA, plc->RDA, sizeof (request->RDA)); memcpy (request->DAK, plc->DAK, sizeof (request->DAK)); request->PEKS = 0x00; } else { Request (plc, "Set Local Network Membership Key"); memset (request->RDA, 0, sizeof (request->RDA)); memset (request->DAK, 0, sizeof (request->DAK)); request->PEKS = 0x0F; } if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_SET_KEY | MMTYPE_CNF)) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD); return (-1); } if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } Confirm (plc, "Setting ..."); return (0); }
signed ModuleWrite (struct plc * plc, struct _file_ * file, unsigned index, struct vs_module_spec * vs_module_spec) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_module_operation_write_request { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint32_t RESERVED; uint8_t NUM_OP_DATA; struct __packed { uint16_t MOD_OP; uint16_t MOD_OP_DATA_LEN; uint32_t MOD_OP_RSVD; uint32_t MOD_OP_SESSION_ID; uint8_t MODULE_IDX; uint16_t MODULE_ID; uint16_t MODULE_SUB_ID; uint16_t MODULE_LENGTH; uint32_t MODULE_OFFSET; } MODULE_SPEC; uint8_t MODULE_DATA [PLC_MODULE_SIZE]; } * request = (struct vs_module_operation_write_request *)(message); struct __packed vs_module_operation_write_confirm { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint16_t MSTATUS; uint16_t ERR_REC_CODE; uint32_t RESERVED; uint8_t NUM_OP_DATA; struct __packed { uint16_t MOD_OP; uint16_t MOD_OP_DATA_LEN; uint32_t MOD_OP_RSVD; uint32_t MOD_OP_SESSION_ID; uint8_t MODULE_IDX; uint16_t MODULE_ID; uint16_t MODULE_SUB_ID; uint16_t MODULE_LENGTH; uint32_t MODULE_OFFSET; } MODULE_SPEC; } * confirm = (struct vs_module_operation_write_confirm *)(message); #ifndef __GNUC__ #pragma pack (pop) #endif unsigned timeout = channel->timeout; uint16_t length = PLC_MODULE_SIZE; uint32_t extent = vs_module_spec->MODULE_LENGTH; uint32_t offset = 0; Request (plc, "Flash %s", file->name); while (extent) { memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, HOMEPLUG_MTYPE); QualcommHeader (&request->qualcomm, 0, (VS_MODULE_OPERATION | MMTYPE_REQ)); plc->packetsize = sizeof (struct vs_module_operation_write_request); if (length > extent) { length = extent; } if (read (file->file, request->MODULE_DATA, length) != length) { error (1, errno, FILE_CANTREAD, file->name); } request->NUM_OP_DATA = 1; request->MODULE_SPEC.MOD_OP = HTOLE16 (PLC_MOD_OP_WRITE_MODULE); request->MODULE_SPEC.MOD_OP_DATA_LEN = HTOLE16 (sizeof (request->MODULE_SPEC) + sizeof (request->MODULE_DATA)); request->MODULE_SPEC.MOD_OP_SESSION_ID = HTOLE32 (plc->cookie); request->MODULE_SPEC.MODULE_IDX = index; request->MODULE_SPEC.MODULE_ID = HTOLE16 (vs_module_spec->MODULE_ID); request->MODULE_SPEC.MODULE_SUB_ID = HTOLE16 (vs_module_spec->MODULE_SUB_ID); request->MODULE_SPEC.MODULE_LENGTH = HTOLE16 (length); request->MODULE_SPEC.MODULE_OFFSET = HTOLE32 (offset); #if 0 fprintf (stderr, "RESERVED 0x%08X\n", LE32TOH (request->RESERVED)); fprintf (stderr, "NUM_OP_DATA %d\n", request->NUM_OP_DATA); fprintf (stderr, "MOD_OP 0x%02X\n", LE16TOH (request->MODULE_SPEC.MOD_OP)); fprintf (stderr, "MOD_OP_DATA_LEN %d\n", LE16TOH (request->MODULE_SPEC.MOD_OP_DATA_LEN)); fprintf (stderr, "RESERVED 0x%08X\n", LE32TOH (request->MODULE_SPEC.MOD_OP_RSVD)); fprintf (stderr, "MODULE_ID 0x%04X\n", LE16TOH (request->MODULE_SPEC.MODULE_ID)); fprintf (stderr, "MODULE_SUB_ID 0x%04X\n", LE16TOH (request->MODULE_SPEC.MODULE_SUB_ID)); fprintf (stderr, "MODULE_LENGTH %d\n", LE16TOH (request->MODULE_SPEC.MODULE_LENGTH)); fprintf (stderr, "MODULE_OFFSET 0x%08X\n", LE32TOH (request->MODULE_SPEC.MODULE_OFFSET)); #endif if (SendMME (plc) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTSEND); return (-1); } channel->timeout = PLC_MODULE_WRITE_TIMEOUT; if (ReadMME (plc, 0, (VS_MODULE_OPERATION | MMTYPE_CNF)) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTREAD); channel->timeout = timeout; return (-1); } channel->timeout = timeout; #if 0 fprintf (stderr, "MSTATUS 0x%04X\n", LE16TOH (confirm->MSTATUS)); fprintf (stderr, "ERROR_REC_CODE %d\n", LE16TOH (confirm->ERR_REC_CODE)); fprintf (stderr, "RESERVED 0x%08X\n", LE32TOH (confirm->RESERVED)); fprintf (stderr, "NUM_OP_DATA %d\n", confirm->NUM_OP_DATA); fprintf (stderr, "MOD_OP 0x%02X\n", LE16TOH (request->MODULE_SPEC.MOD_OP)); fprintf (stderr, "MOD_OP_DATA_LEN %d\n", LE16TOH (confirm->MODULE_SPEC.MOD_OP_DATA_LEN)); fprintf (stderr, "RESERVED 0x%08X\n", LE32TOH (confirm->MODULE_SPEC.MOD_OP_RSVD)); fprintf (stderr, "MODULE_ID 0x%04X\n", LE16TOH (confirm->MODULE_SPEC.MODULE_ID)); fprintf (stderr, "MODULE_SUB_ID 0x%04X\n", LE16TOH (confirm->MODULE_SPEC.MODULE_SUB_ID)); fprintf (stderr, "MODULE_LENGTH %d\n", LE16TOH (confirm->MODULE_SPEC.MODULE_LENGTH)); fprintf (stderr, "MODULE_OFFSET 0x%08X\n", LE32TOH (request->MODULE_SPEC.MODULE_OFFSET)); #endif if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } if (LE16TOH (confirm->MODULE_SPEC.MODULE_LENGTH) != length) { error ((plc->flags & PLC_BAILOUT), 0, PLC_ERR_LENGTH); return (-1); } if (LE32TOH (confirm->MODULE_SPEC.MODULE_OFFSET) != offset) { error ((plc->flags & PLC_BAILOUT), 0, PLC_ERR_OFFSET); return (-1); } extent -= length; offset += length; } return (0); }
static signed Diagnostics (struct plc * plc) { char version [PLC_VERSION_STRING]; struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_sw_ver_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint8_t MDEVICEID; uint8_t MVERLENGTH; char MVERSION [PLC_VERSION_STRING]; } * request = (struct vs_sw_ver_request *) (message); struct __packed vs_sw_ver_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint8_t MDEVICEID; uint8_t MVERLENGTH; char MVERSION [PLC_VERSION_STRING]; } * confirm = (struct vs_sw_ver_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_SW_VER | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_SW_VER | MMTYPE_CNF)) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD); return (-1); } if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } memcpy (version, confirm->MVERSION, sizeof (version)); if (plc->action == INT6KLOG_FMT_XML) { printf ("<?xml version='1.0' encoding='utf-8' standalone='yes'?>"); printf ("<Diagnostics>"); PrintWatchdogReport (plc, version); PrintCheckpointReport (plc, version); printf ("</Diagnostics>\n"); return (0); } if (plc->action == INT6KLOG_FMT_RAW) { PrintRawWatchdogReport (plc); return (0); } return (0); }
static signed PrintCheckpointReport (struct plc * plc, char const * version) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_cp_rpt_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint16_t SESSIONID; uint8_t CLR; } * request = (struct vs_cp_rpt_request *) (message); struct __packed vs_cp_rpt_ind { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint8_t MAJORVERSION; uint8_t MINORVERSION; uint8_t RESERVED [14]; uint16_t SESSIONID; uint32_t TOTALBUFFERSIZE; uint32_t BLOCKOFFSET; uint32_t BYTEINDEXOFNEXTPOSITION; uint8_t NUMPARTS; uint8_t CURPART; uint16_t RDATALENGTH; uint8_t RDATAOFFSET; uint8_t RDATA [1]; } * indicate = (struct vs_cp_rpt_ind *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_CP_RPT | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); request->SESSIONID = HTOLE16 (plc->cookie); request->CLR = plc->readaction; if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } printf ("<CheckpointReport>"); do { if (ReadMME (plc, 0, (VS_CP_RPT | MMTYPE_IND)) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD); return (-1); } if (_anyset (indicate->MSTATUS, MSTATUS_STATUS)) { Failure (plc, PLC_WONTDOIT); return (-1); } printf ("<Packet>"); printf ("<Version>%s</Version>", version); printf ("<Status>0</Status>"); printf ("<MajorVersionBit>%d</MajorVersionBit>", indicate->MSTATUS & MSTATUS_MAJORVERSION? 1:0); printf ("<BufferIsLocked>%d</BufferIsLocked>", indicate->MSTATUS & MSTATUS_BUFFERISLOCKED? 1:0); printf ("<AutoLockOnResetIsOn>%d</AutoLockOnResetIsOn>", indicate->MSTATUS & MSTATUS_AUTOLOCKONRESET? 1:0); printf ("<UnsolicitedUpdatesIsOn>%d</UnsolicitedUpdatesIsOn>", indicate->MSTATUS & MSTATUS_UNSOLICITEDUPDATES? 1:0); printf ("<Unsolicited>%d</Unsolicited>", indicate->MSTATUS & MSTATUS_UNSOLICITED? 1:0); printf ("<MajorVersion>%d</MajorVersion>", indicate->MAJORVERSION); printf ("<MinorVersion>%d</MinorVersion>", indicate->MINORVERSION); printf ("<Reserved1>0</Reserved1>"); printf ("<Reserved2>0</Reserved2>"); printf ("<Reserved3>0</Reserved3>"); printf ("<Reserved4>0</Reserved4>"); printf ("<SessionId>1</SessionId>"); printf ("<TotalBufferSize>%d</TotalBufferSize>", LE32TOH (indicate->TOTALBUFFERSIZE)); printf ("<BlockOffset>%d</BlockOffset>", LE32TOH (indicate->BLOCKOFFSET)); printf ("<ByteIndexOfNextPos>%d</ByteIndexOfNextPos>", LE32TOH (indicate->BYTEINDEXOFNEXTPOSITION)); printf ("<NumParts>%d</NumParts>", indicate->NUMPARTS); printf ("<CurPart>%d</CurPart>", indicate->CURPART); printf ("<RDataLength>%d</RDataLength>", LE16TOH (indicate->RDATALENGTH)); printf ("<RDataOffset>%d</RDataOffset>", indicate->RDATAOFFSET); printf ("<RData>"); b64dump (indicate->RDATA + indicate->RDATAOFFSET, LE16TOH (indicate->RDATALENGTH), 0, stdout); printf ("</RData>"); printf ("</Packet>"); } while (indicate->CURPART < indicate->NUMPARTS); printf ("</CheckpointReport>"); return (0); }
static signed PrintWatchdogReport (struct plc * plc, char const * version) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_wd_rpt_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint16_t SESSIONID; uint8_t CLR; } * request = (struct vs_wd_rpt_request *) (message); struct __packed vs_wd_rpt_ind { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint16_t SESSIONID; uint8_t NUMPARTS; uint8_t CURPART; uint16_t RDATALENGTH; uint8_t RDATAOFFSET; uint8_t RDATA [1]; } * indicate = (struct vs_wd_rpt_ind *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_WD_RPT | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); request->SESSIONID = HTOLE16 (plc->cookie); request->CLR = plc->readaction; if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } printf ("<WatchdogReport>"); do { if (ReadMME (plc, 0, (VS_WD_RPT | MMTYPE_IND)) < 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD); return (-1); } if (indicate->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } printf ("<Packet>"); printf ("<Version>%s</Version>", version); printf ("<OUI>%s</OUI>", "00B052"); printf ("<Status>0</Status>"); printf ("<SessionId>0</SessionId>"); printf ("<NumParts>%d</NumParts>", indicate->NUMPARTS); printf ("<CurPart>%d</CurPart>", indicate->CURPART); printf ("<DataLength>%d</DataLength>", LE16TOH (indicate->RDATALENGTH)); printf ("<DataOffset>%d</DataOffset>", indicate->RDATAOFFSET); printf ("<Data>"); b64dump (indicate->RDATA + indicate->RDATAOFFSET, LE16TOH (indicate->RDATALENGTH) - indicate->RDATAOFFSET, 0, stdout); printf ("</Data>"); printf ("</Packet>"); } while (indicate->CURPART < indicate->NUMPARTS); printf ("</WatchdogReport>"); return (0); }
static signed PrintRawWatchdogReport (struct plc * plc) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_wd_rpt_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint16_t SESSIONID; uint8_t CLR; } * request = (struct vs_wd_rpt_request *) (message); struct __packed vs_wd_rpt_indicate { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint16_t SESSIONID; uint8_t NUMPARTS; uint8_t CURPART; uint16_t RDATALENGTH; uint8_t RDATAOFFSET; uint8_t RDATA [1]; } * indicate = (struct vs_wd_rpt_indicate *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_WD_RPT | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); request->SESSIONID = HTOLE16 (plc->cookie); request->CLR = plc->readaction; if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } do { printf ("%d %d\n", LE16TOH (indicate->RDATALENGTH), indicate->RDATAOFFSET); if (ReadMME (plc, 0, (VS_WD_RPT | MMTYPE_IND)) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD); return (-1); } printf ("%d %d\n", LE16TOH (indicate->RDATALENGTH), indicate->RDATAOFFSET); if (indicate->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } printf ("%d %d\n", LE16TOH (indicate->RDATALENGTH), indicate->RDATAOFFSET); write (STDOUT_FILENO, indicate->RDATA + indicate->RDATAOFFSET, LE16TOH (indicate->RDATALENGTH) - indicate->RDATAOFFSET); } while (indicate->CURPART < indicate->NUMPARTS); return (0); }
signed WriteExecuteFirmware1 (struct plc * plc, unsigned module, const struct nvm_header1 * nvm_header) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_write_execute_request { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint32_t CLIENT_SESSION_ID; uint32_t SERVER_SESSION_ID; uint32_t FLAGS; uint8_t ALLOWED_MEM_TYPES [8]; uint32_t TOTAL_LENGTH; uint32_t CURR_PART_LENGTH; uint32_t CURR_PART_OFFSET; uint32_t START_ADDR; uint32_t CHECKSUM; uint8_t RESERVED2 [8]; uint8_t IMAGE [PLC_MODULE_SIZE]; } * request = (struct vs_write_execute_request *) (message); struct __packed vs_write_execute_confirm { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint32_t MSTATUS; uint32_t CLIENT_SESSION_ID; uint32_t SERVER_SESSION_ID; uint32_t FLAGS; uint8_t ALLOWED_MEM_TYPES [8]; uint32_t TOTAL_LENGTH; uint32_t CURR_PART_LENGTH; uint32_t CURR_PART_OFFSET; uint32_t START_ADDR; uint32_t CHECKSUM; uint8_t RESERVED2 [8]; uint32_t CURR_PART_ABSOLUTE_ADDR; uint32_t ABSOLUTE_START_ADDR; } * confirm = (struct vs_write_execute_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif unsigned action = PLC_MODULE_ABSOLUTE; uint32_t length = PLC_MODULE_SIZE; uint32_t offset = LE32TOH (nvm_header->IMAGEADDRESS); uint32_t extent = LE32TOH (nvm_header->IMAGELENGTH); Request (plc, "Write %s (%d) (%08X:%d)", plc->NVM.name, module, offset, extent); while (extent) { memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_WRITE_AND_EXECUTE_APPLET | MMTYPE_REQ)); if (length > extent) { Request (plc, "Start %s (%d) (%08X)", plc->NVM.name, module, LE32TOH (nvm_header->ENTRYPOINT)); length = extent; action |= PLC_MODULE_EXECUTE; } if (read (plc->NVM.file, request->IMAGE, length) != (signed)(length)) { error (1, errno, FILE_CANTREAD, plc->NVM.name); } request->CLIENT_SESSION_ID = HTOLE32 (plc->cookie); request->SERVER_SESSION_ID = HTOLE32 (0); request->FLAGS = HTOLE32 (action); request->ALLOWED_MEM_TYPES [0] = 1; request->TOTAL_LENGTH = nvm_header->IMAGELENGTH; request->CURR_PART_LENGTH = HTOLE32 (length); request->CURR_PART_OFFSET = HTOLE32 (offset); request->START_ADDR = nvm_header->ENTRYPOINT; request->CHECKSUM = nvm_header->IMAGECHECKSUM; plc->packetsize = sizeof (* request); if (SendMME (plc) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_WRITE_AND_EXECUTE_APPLET | MMTYPE_CNF)) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTREAD); return (-1); } if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } if (LE32TOH (confirm->CURR_PART_LENGTH) != length) { error ((plc->flags & PLC_BAILOUT), 0, PLC_ERR_LENGTH); return (-1); } if (LE32TOH (confirm->CURR_PART_OFFSET) != offset) { error ((plc->flags & PLC_BAILOUT), 0, PLC_ERR_OFFSET); return (-1); } offset += length; extent -= length; } return (0); }
signed Identity1 (struct plc * plc) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_rd_mod_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MODULEID; uint8_t MACCESS; uint16_t MLENGTH; uint32_t MOFFSET; uint8_t MSECRET [16]; } * request = (struct vs_rd_mod_request *) (message); struct __packed vs_rd_mod_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint8_t RES [3]; uint8_t MODULEID; uint8_t RESERVED; uint16_t MLENGTH; uint32_t MOFFSET; uint32_t MCHKSUM; uint8_t BUFFER [PLC_RECORD_SIZE]; } * confirm = (struct vs_rd_mod_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (plc, "Device Identity"); memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_RD_MOD | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); request->MODULEID = VS_MODULE_PIB; request->MLENGTH = HTOLE16 (sizeof (confirm->BUFFER)); request->MOFFSET = HTOLE32 (0); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } while (ReadMME (plc, 0, (VS_RD_MOD | MMTYPE_CNF)) > 0) { if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); continue; } Confirm (plc, "-------"); pibpeek1 (confirm->BUFFER); } return (0); }
signed ReadFirmware1 (struct plc * plc) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_rd_mod_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MODULEID; uint8_t MACCESS; uint16_t MLENGTH; uint32_t MOFFSET; uint8_t MSECRET [16]; } * request = (struct vs_rd_mod_request *) (message); struct __packed vs_rd_mod_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint8_t RES [3]; uint8_t MODULEID; uint8_t RESERVED; uint16_t MLENGTH; uint32_t MOFFSET; uint32_t CHKSUM; uint8_t BUFFER [PLC_RECORD_SIZE]; } * confirm = (struct vs_rd_mod_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif uint32_t header = 0; uint32_t extent = 0; uint32_t offset = 0; uint16_t length = PLC_RECORD_SIZE; Request (plc, "Read Firmware from Device"); if (lseek (plc->nvm.file, 0, SEEK_SET)) { error (PLC_EXIT (plc), errno, FILE_CANTHOME, plc->nvm.name); return (1); } do { memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_RD_MOD | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); request->MODULEID = VS_MODULE_MAC; request->MLENGTH = HTOLE16 (length); request->MOFFSET = HTOLE32 (offset); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_RD_MOD | MMTYPE_CNF)) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD); return (-1); } if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } if (LE16TOH (confirm->MLENGTH) != length) { error (PLC_EXIT (plc), 0, PLC_ERR_LENGTH); return (-1); } if (LE32TOH (confirm->MOFFSET) != offset) { error (PLC_EXIT (plc), 0, PLC_ERR_OFFSET); return (-1); } length = LE16TOH (confirm->MLENGTH); offset = LE32TOH (confirm->MOFFSET); if (checksum32 (confirm->BUFFER, length, confirm->CHKSUM)) { error (PLC_EXIT (plc), ECANCELED, "Bad Packet Checksum"); return (-1); } if (offset == extent) { struct nvm_header1 * nvm_header = (struct nvm_header1 *)(confirm->BUFFER); if (checksum32 (nvm_header, sizeof (* nvm_header), 0)) { error (PLC_EXIT (plc), ECANCELED, "Bad Header Checksum"); return (-1); } if (LE32TOH (nvm_header->HEADERVERSION) != 0x60000000) { error (PLC_EXIT (plc), ECANCELED, "Bad Header Version"); return (-1); } extent += sizeof (* nvm_header); extent += LE32TOH (nvm_header->IMAGELENGTH); header = LE32TOH (nvm_header->NEXTHEADER); } if ((offset + length) > extent) { length = extent - offset; } if (lseek (plc->nvm.file, offset, SEEK_SET) != (off_t)(offset)) { error (PLC_EXIT (plc), errno, FILE_CANTSEEK, plc->nvm.name); return (-1); } if (write (plc->nvm.file, confirm->BUFFER, length) != (signed)(length)) { error (PLC_EXIT (plc), errno, FILE_CANTSEEK, plc->nvm.name); return (-1); } offset += length; length = 1024; } while ((header) || (offset < extent)); Confirm (plc, "Read %s", plc->nvm.name); return (0); }
signed SetProperty (struct plc * plc, struct plcproperty * plcproperty) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_set_property_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint32_t COOKIE; uint8_t OPTION; uint8_t RESERVED [3]; uint32_t PROP_VERSION; uint32_t PROP_NUMBER; uint32_t DATA_LENGTH; uint8_t DATA_BUFFER [256]; } * request = (struct vs_set_property_request *) (message); struct __packed vs_set_property_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint32_t MSTATUS; uint32_t COOKIE; } * confirm = (struct vs_set_property_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (plc, "Set Property"); memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_SET_PROPERTY | MMTYPE_REQ)); request->COOKIE = HTOLE32 (plc->cookie); request->OPTION = plcproperty->PROP_OPTION; request->PROP_VERSION = HTOLE32 (plcproperty->PROP_VERSION); request->PROP_NUMBER = HTOLE32 (plcproperty->PROP_NUMBER); request->DATA_LENGTH = HTOLE32 (plcproperty->DATA_LENGTH); memcpy (&request->DATA_BUFFER, &plcproperty->DATA_BUFFER, plcproperty->DATA_LENGTH); plc->packetsize = sizeof (* request); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } while (ReadMME (plc, 0, (VS_SET_PROPERTY | MMTYPE_CNF)) > 0) { if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); continue; } } return (0); }
static signed con_info (struct plc * plc, uint8_t TYPE, uint16_t CID, uint16_t TOT_BW_USED) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_con_info_req { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t REQ_TYPE; uint32_t RSVD; uint16_t CSPEC_VER; uint16_t CID; uint16_t TOT_BW_USED; } * request = (struct vs_con_info_req *)(message); struct __packed vs_con_info_cnf { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t REQ_TYPE; uint8_t MSTATUS; uint16_t ERR_REC_CODE; uint32_t RSVD; uint8_t NUM_CONN; struct conn_info CONN_INFO [64]; } * confirm = (struct vs_con_info_cnf *)(message); struct conn_info * conn_info = (struct conn_info*)(confirm->CONN_INFO); struct vs_con_info_cnf * indicate = (struct vs_con_info_cnf *)(message); #ifndef __GNUC__ #pragma pack (pop) #endif int i; Request (plc, "COQOS connection information"); memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_CONN_INFO | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); request->REQ_TYPE = TYPE; request->CID = CID; request->TOT_BW_USED = TOT_BW_USED; request->CSPEC_VER = 0x01; if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } while (ReadMME (plc, 0, (VS_CONN_INFO | MMTYPE_CNF)) <= 0); if (confirm->MSTATUS) { Failure (plc, "Error requesting information."); return (-1); } /* BW exceeded request and "cancel all requests" do not send indicate */ if ((TYPE == CONTROL_BW) || (TYPE == CONTROL_BWC)) { Confirm (plc, "Success"); return (0); } Confirm (plc, "Received confirm, waiting for indicate..."); while (ReadMME (plc, 0, (VS_CONN_INFO | MMTYPE_IND)) <= 0); if (indicate->MSTATUS) { Failure (plc, "Error requesting information."); return (-1); } printf ("Number of Connections: %d\n", (int)indicate->NUM_CONN); conn_info = (struct conn_info *)(indicate->CONN_INFO); for (i = 0; i < indicate->NUM_CONN; i++) { printf ("SNID: %02X ", conn_info->SNID); printf ("CID: %04X ", conn_info->CID); printf ("STEI: %02X ", conn_info->STEI); printf ("DTEI: %02X ", conn_info->DTEI); printf ("LLID: %02X ", conn_info->LLID); printf ("CSPEC_VERSION: %04X ", conn_info->CSPECVERSION); printf ("CONN_CAP: %02d ", conn_info->CONN_CAP); printf ("CONN_COQOS_PRIO: %02d ", conn_info->CONN_COQOS_PRIO); printf ("CONN_RATE: %d ", conn_info->CONN_RATE); printf ("CONN_TTL: %d ", conn_info->CONN_TTL); printf ("BW_USED: %d \n", conn_info->BW_USED); conn_info++; } return (0); }
signed WriteMOD (struct plc * plc, uint8_t module, void const * memory, size_t extent) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_wr_mod_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MODULEID; uint8_t MACCESS; uint16_t MLENGTH; uint32_t MOFFSET; uint32_t MCHKSUM; uint8_t MBUFFER [PLC_RECORD_SIZE]; } * request = (struct vs_wr_mod_request *) (message); struct __packed vs_wr_mod_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint8_t MODULEID; uint8_t MACCESS; uint16_t MLENGTH; uint32_t MOFFSET; } * confirm = (struct vs_wr_mod_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif uint32_t length = PLC_RECORD_SIZE; uint32_t offset = 0; while (extent) { memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_WR_MOD | MMTYPE_REQ)); if (length > extent) { length = (signed)(extent); } memcpy (request->MBUFFER, (byte *)(memory) + offset, length); request->MODULEID = module; request->MACCESS = 0; request->MLENGTH = HTOLE16 (length); request->MOFFSET = HTOLE32 (offset); request->MCHKSUM = checksum32 (request->MBUFFER, length, 0); plc->packetsize = sizeof (* request); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_WR_MOD | MMTYPE_CNF)) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD); return (-1); } if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } if (LE16TOH (confirm->MLENGTH) != length) { error (PLC_EXIT (plc), 0, PLC_ERR_LENGTH); return (-1); } if (LE32TOH (confirm->MOFFSET) != offset) { error (PLC_EXIT (plc), 0, PLC_ERR_OFFSET); return (-1); } offset += length; extent -= length; } return (0); }
signed ResetAndWait (struct plc * plc) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); struct timeval ts; struct timeval tc; unsigned timer = 0; #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_rs_dev_request { struct ethernet_std ethernet; struct qualcomm_std qualcomm; } * request = (struct vs_rs_dev_request *) (message); struct __packed vs_rs_dev_confirm { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint8_t MSTATUS; } * confirm = (struct vs_rs_dev_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (plc, "Reset when Ready"); if (gettimeofday (&ts, NULL) == -1) { error (1, errno, CANT_START_TIMER); } for (timer = 0; timer < plc->timer; timer = SECONDS (ts, tc)) { memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_RS_DEV | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); if (SendMME (plc) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_RS_DEV | MMTYPE_CNF)) < 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTREAD); return (-1); } if (gettimeofday (&tc, NULL) == -1) { error (1, errno, CANT_RESET_TIMER); } if (plc->packetsize) { if (!confirm->MSTATUS) { Confirm (plc, "Resetting ..."); return (0); } } } return (-1); }