| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 1 | #include <stdio.h> | 
 | 2 | #include <string.h> | 
 | 3 | #include <stdint.h> | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 4 | #include <malloc.h> | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 5 |  | 
 | 6 |  | 
| Chris Austen | 0012e9b | 2015-10-22 01:37:46 -0500 | [diff] [blame] | 7 | extern uint8_t find_sensor(uint8_t); | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 8 | extern int set_sensor_dbus_state_v(uint8_t , const char *, char *); | 
 | 9 |  | 
 | 10 |  | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 11 | struct sensorRES_t { | 
 | 12 | 	uint8_t sensor_number; | 
 | 13 | 	uint8_t operation; | 
 | 14 | 	uint8_t sensor_reading; | 
 | 15 | 	uint8_t assert_state7_0; | 
 | 16 | 	uint8_t assert_state14_8;	 | 
 | 17 | 	uint8_t deassert_state7_0; | 
 | 18 | 	uint8_t deassert_state14_8;	 | 
 | 19 | 	uint8_t event_data1; | 
 | 20 | 	uint8_t event_data2; | 
 | 21 | 	uint8_t event_data3;	 | 
 | 22 | } __attribute__ ((packed)); | 
 | 23 |  | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 24 | #define ISBITSET(x,y) (((x)>>(y))&0x01) | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 25 | #define ASSERTINDEX 0 | 
 | 26 | #define DEASSERTINDEX 1 | 
 | 27 |  | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 28 | // Sensor Type,  Offset, function handler, Dbus Method, Assert value, Deassert value | 
 | 29 | struct lookup_t { | 
 | 30 | 	uint8_t sensor_type; | 
 | 31 | 	uint8_t offset; | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 32 | 	int (*func)(const sensorRES_t *, const lookup_t *, const char *); | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 33 | 	char    method[16]; | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 34 | 	char    assertion[64]; | 
 | 35 | 	char    deassertion[64]; | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 36 | }; | 
 | 37 |  | 
 | 38 |  | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 39 | extern int updateDbusInterface(uint8_t , const char *, const char *) ; | 
 | 40 | extern int set_sensor_dbus_state(uint8_t ,const char *, const char *); | 
 | 41 |  | 
 | 42 |  | 
 | 43 | int set_sensor_dbus_state_simple(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { | 
 | 44 |  | 
 | 45 | 	return set_sensor_dbus_state(pRec->sensor_number, pTable->method, value); | 
 | 46 | } | 
 | 47 |  | 
 | 48 | struct event_data_t { | 
 | 49 | 	uint8_t data; | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 50 | 	char    text[64]; | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 51 | }; | 
 | 52 |  | 
 | 53 | event_data_t g_fwprogress02h[] = { | 
 | 54 | 	{0x00, "Unspecified"}, | 
 | 55 | 	{0x01, "Memory Init"}, | 
 | 56 | 	{0x02, "HD Init"}, | 
 | 57 | 	{0x03, "Secondary Proc Init"}, | 
 | 58 | 	{0x04, "User Authentication"}, | 
 | 59 | 	{0x05, "User init system setup"}, | 
 | 60 | 	{0x06, "USB configuration"}, | 
 | 61 | 	{0x07, "PCI configuration"}, | 
 | 62 | 	{0x08, "Option ROM Init"}, | 
 | 63 | 	{0x09, "Video Init"}, | 
 | 64 | 	{0x0A, "Cache Init"}, | 
 | 65 | 	{0x0B, "SM Bus init"}, | 
 | 66 | 	{0x0C, "Keyboard Init"}, | 
 | 67 | 	{0x0D, "Embedded ctrl init"}, | 
 | 68 | 	{0x0E, "Docking station attachment"}, | 
 | 69 | 	{0x0F, "Enable docking station"}, | 
 | 70 | 	{0x10, "Docking station ejection"}, | 
 | 71 | 	{0x11, "Disabling docking station"}, | 
 | 72 | 	{0x12, "Calling OS Wakeup"}, | 
 | 73 | 	{0x13, "Starting OS"}, | 
 | 74 | 	{0x14, "Baseboard Init"}, | 
 | 75 | 	{0x15, ""}, | 
 | 76 | 	{0x16, "Floppy Init"}, | 
 | 77 | 	{0x17, "Keyboard Test"}, | 
 | 78 | 	{0x18, "Pointing Device Test"}, | 
 | 79 | 	{0x19, "Primary Proc Init"}, | 
 | 80 | 	{0xFF, "Unknown"} | 
 | 81 | }; | 
 | 82 |  | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 83 | event_data_t g_fwprogress00h[] = { | 
 | 84 | 	{0x00, "Unspecified."}, | 
 | 85 | 	{0x01, "No system memory detected"}, | 
 | 86 | 	{0x02, "No usable system memory"}, | 
 | 87 | 	{0x03, "Unrecoverable hard-disk/ATAPI/IDE"}, | 
 | 88 | 	{0x04, "Unrecoverable system-board"}, | 
 | 89 | 	{0x05, "Unrecoverable diskette"}, | 
 | 90 | 	{0x06, "Unrecoverable hard-disk controller"}, | 
 | 91 | 	{0x07, "Unrecoverable PS/2 or USB keyboard"}, | 
 | 92 | 	{0x08, "Removable boot media not found"}, | 
 | 93 | 	{0x09, "Unrecoverable video controller"}, | 
 | 94 | 	{0x0A, "No video device detected"}, | 
 | 95 | 	{0x0B, "Firmware ROM corruption detected"}, | 
 | 96 | 	{0x0C, "CPU voltage mismatch"}, | 
 | 97 | 	{0x0D, "CPU speed matching"}, | 
 | 98 | 	{0xFF, "unknown"}, | 
 | 99 | }; | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 100 |  | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 101 |  | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 102 | char *event_data_lookup(event_data_t *p, uint8_t b) { | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 103 |  | 
| Chris Austen | 5a9f0b4 | 2015-10-21 20:32:19 -0500 | [diff] [blame] | 104 | 	while(p->data != 0xFF) { | 
 | 105 | 		if (p->data == b) { | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 106 | 			break; | 
| Chris Austen | 0012e9b | 2015-10-22 01:37:46 -0500 | [diff] [blame] | 107 | 		} | 
| Chris Austen | 5a9f0b4 | 2015-10-21 20:32:19 -0500 | [diff] [blame] | 108 | 		p++; | 
 | 109 | 	} | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 110 |  | 
| Chris Austen | 5a9f0b4 | 2015-10-21 20:32:19 -0500 | [diff] [blame] | 111 | 	return p->text; | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 112 | } | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 113 |  | 
 | 114 |  | 
 | 115 |  | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 116 | //  The fw progress sensor contains some additional information that needs to be processed | 
 | 117 | //  prior to calling the dbus code.   | 
 | 118 | int set_sensor_dbus_state_fwprogress(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { | 
 | 119 |  | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 120 | 	char valuestring[128]; | 
| Chris Austen | 0012e9b | 2015-10-22 01:37:46 -0500 | [diff] [blame] | 121 | 	char* p = valuestring; | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 122 |  | 
 | 123 | 	switch (pTable->offset) { | 
 | 124 |  | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 125 | 		case 0x00 : snprintf(p, sizeof(valuestring), "POST Error, %s", event_data_lookup(g_fwprogress00h, pRec->event_data2)); | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 126 | 					break; | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 127 | 		case 0x01 : /* Using g_fwprogress02h for 0x01 because thats what the ipmi spec says to do */ | 
 | 128 | 					snprintf(p, sizeof(valuestring), "FW Hang, %s", event_data_lookup(g_fwprogress02h, pRec->event_data2)); | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 129 | 					break; | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 130 | 		case 0x02 : snprintf(p, sizeof(valuestring), "FW Progress, %s", event_data_lookup(g_fwprogress02h, pRec->event_data2)); | 
| Chris Austen | 0012e9b | 2015-10-22 01:37:46 -0500 | [diff] [blame] | 131 | 					break; | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 132 | 	} | 
 | 133 |  | 
| Chris Austen | 0012e9b | 2015-10-22 01:37:46 -0500 | [diff] [blame] | 134 | 	return set_sensor_dbus_state_v(pRec->sensor_number, pTable->method, p); | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 135 | } | 
 | 136 |  | 
| Chris Austen | 0a4e247 | 2015-10-18 12:19:40 -0500 | [diff] [blame] | 137 | // Handling this special OEM sensor by coping what is in byte 4.  I also think that is odd | 
 | 138 | // considering byte 3 is for sensor reading.  This seems like a misuse of the IPMI spec | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 139 | int set_sensor_dbus_state_osbootcount(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { | 
| Chris Austen | 0a4e247 | 2015-10-18 12:19:40 -0500 | [diff] [blame] | 140 | 	char valuestring[32]; | 
 | 141 | 	char* pStr = valuestring; | 
 | 142 |  | 
 | 143 | 	sprintf(valuestring, "%d", pRec->assert_state7_0); | 
 | 144 |  | 
 | 145 | 	return set_sensor_dbus_state_v(pRec->sensor_number, pTable->method, pStr); | 
 | 146 | } | 
 | 147 |  | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 148 |  | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 149 |  | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 150 | //  This table lists only senors we care about telling dbus about. | 
| Chris Austen | 0012e9b | 2015-10-22 01:37:46 -0500 | [diff] [blame] | 151 | //  Offset definition cab be found in section 42.2 of the IPMI 2.0 | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 152 | //  spec.  Add more if/when there are more items of interest. | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 153 | lookup_t g_ipmidbuslookup[] = { | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 154 |  | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 155 | 	{0xe9, 0x00, set_sensor_dbus_state_simple, "setValue", "Disabled", ""}, // OCC Inactive 0 | 
 | 156 | 	{0xe9, 0x01, set_sensor_dbus_state_simple, "setValue", "Enabled", ""},   // OCC Active 1 | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 157 | 	{0x07, 0x07, set_sensor_dbus_state_simple, "setPresent", "True", "False"}, | 
| Chris Austen | f3644f1 | 2015-10-31 12:46:39 -0500 | [diff] [blame] | 158 | 	{0x07, 0x08, set_sensor_dbus_state_simple, "setFault",   "True", ""}, | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 159 | 	{0x0C, 0x06, set_sensor_dbus_state_simple, "setPresent", "True", "False"}, | 
| Chris Austen | f3644f1 | 2015-10-31 12:46:39 -0500 | [diff] [blame] | 160 | 	{0x0C, 0x04, set_sensor_dbus_state_simple, "setFault",   "True", ""}, | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 161 | 	{0x0F, 0x02, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"}, | 
 | 162 | 	{0x0F, 0x01, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"}, | 
 | 163 | 	{0x0F, 0x00, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"}, | 
| Chris Austen | f3644f1 | 2015-10-31 12:46:39 -0500 | [diff] [blame] | 164 | 	{0xC7, 0x01, set_sensor_dbus_state_simple, "setFault", "True", ""}, | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 165 | 	{0xc3, 0x00, set_sensor_dbus_state_osbootcount, "setValue", "" ,""}, | 
 | 166 | 	{0x1F, 0x00, set_sensor_dbus_state_simple, "setValue", "Boot completed (00)", ""}, | 
 | 167 | 	{0x1F, 0x01, set_sensor_dbus_state_simple, "setValue", "Boot completed (01)", ""}, | 
 | 168 | 	{0x1F, 0x02, set_sensor_dbus_state_simple, "setValue", "PXE boot completed", ""}, | 
 | 169 | 	{0x1F, 0x03, set_sensor_dbus_state_simple, "setValue", "Diagnostic boot completed", ""}, | 
 | 170 | 	{0x1F, 0x04, set_sensor_dbus_state_simple, "setValue", "CD-ROM boot completed", ""}, | 
 | 171 | 	{0x1F, 0x05, set_sensor_dbus_state_simple, "setValue", "ROM boot completed", ""}, | 
 | 172 | 	{0x1F, 0x06, set_sensor_dbus_state_simple, "setValue", "Boot completed (06)", ""}, | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 173 |  | 
 | 174 | 	{0xFF, 0xFF, NULL, "", "", ""} | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 175 | }; | 
 | 176 |  | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 177 |  | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 178 | void reportSensorEventAssert(sensorRES_t *pRec, int index) { | 
 | 179 | 	lookup_t *pTable = &g_ipmidbuslookup[index]; | 
 | 180 | 	(*pTable->func)(pRec, pTable, pTable->assertion); | 
 | 181 | } | 
 | 182 | void reportSensorEventDeassert(sensorRES_t *pRec, int index) { | 
 | 183 | 	lookup_t *pTable = &g_ipmidbuslookup[index]; | 
 | 184 | 	(*pTable->func)(pRec, pTable, pTable->deassertion); | 
 | 185 | } | 
 | 186 |  | 
 | 187 |  | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 188 | int findindex(const uint8_t sensor_type, int offset, int *index) { | 
 | 189 | 	 | 
 | 190 | 	int i=0, rc=0; | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 191 | 	lookup_t *pTable = g_ipmidbuslookup; | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 192 |  | 
 | 193 | 	do { | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 194 | 		if ( ((pTable+i)->sensor_type == sensor_type) &&  | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 195 | 			 ((pTable+i)->offset  == offset) ) { | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 196 | 			rc = 1; | 
 | 197 | 			*index = i; | 
 | 198 | 			break; | 
 | 199 | 		} | 
 | 200 | 		i++; | 
 | 201 | 	} while ((pTable+i)->sensor_type  != 0xFF); | 
 | 202 |  | 
 | 203 | 	return rc; | 
 | 204 | } | 
 | 205 |  | 
| Chris Austen | 0a4e247 | 2015-10-18 12:19:40 -0500 | [diff] [blame] | 206 | void debug_print_ok_to_dont_care(uint8_t stype, int offset) | 
 | 207 | { | 
| Chris Austen | 0012e9b | 2015-10-22 01:37:46 -0500 | [diff] [blame] | 208 | 	printf("LOOKATME: Sensor should not be reported:  Type 0x%02x, Offset 0x%02x\n", | 
| Chris Austen | 0a4e247 | 2015-10-18 12:19:40 -0500 | [diff] [blame] | 209 | 		stype, offset); | 
 | 210 | } | 
 | 211 |  | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 212 | bool shouldReport(uint8_t sensorType, int offset, int *index) { | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 213 |  | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 214 | 	bool rc = false; | 
| Chris Austen | 0a4e247 | 2015-10-18 12:19:40 -0500 | [diff] [blame] | 215 |  | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 216 | 	if (findindex(sensorType, offset, index)) { rc = true;	} | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 217 |  | 
| Chris Austen | 0a4e247 | 2015-10-18 12:19:40 -0500 | [diff] [blame] | 218 | 	if (rc==false) { debug_print_ok_to_dont_care(sensorType, offset); } | 
 | 219 |  | 
| Chris Austen | 0130d6e | 2015-10-15 22:32:36 -0500 | [diff] [blame] | 220 | 	return rc; | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 221 | } | 
 | 222 |  | 
 | 223 |  | 
 | 224 | int updateSensorRecordFromSSRAESC(const void *record) { | 
 | 225 |  | 
 | 226 | 	sensorRES_t *pRec = (sensorRES_t *) record; | 
| Chris Austen | 0012e9b | 2015-10-22 01:37:46 -0500 | [diff] [blame] | 227 | 	uint8_t stype; | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 228 | 	int index, i=0; | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 229 |  | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 230 | 	stype = find_sensor(pRec->sensor_number); | 
| Chris Austen | 0012e9b | 2015-10-22 01:37:46 -0500 | [diff] [blame] | 231 |  | 
 | 232 | 	// 0xC3 types use the assertion7_0 for the value to be set | 
 | 233 | 	// so skip the reseach and call the correct event reporting | 
 | 234 | 	// function | 
 | 235 | 	if (stype == 0xC3) { | 
 | 236 |  | 
 | 237 | 		shouldReport(stype, 0x00, &index); | 
 | 238 | 		reportSensorEventAssert(pRec, index); | 
 | 239 |  | 
 | 240 | 	} else { | 
 | 241 | 		// Scroll through each bit position .  Determine | 
 | 242 | 		// if any bit is either asserted or Deasserted. | 
 | 243 | 		for(i=0;i<8;i++) { | 
| Chris Austen | d7cf0e4 | 2015-11-07 14:27:12 -0600 | [diff] [blame] | 244 |  | 
| Chris Austen | 0012e9b | 2015-10-22 01:37:46 -0500 | [diff] [blame] | 245 | 			if ((ISBITSET(pRec->assert_state7_0,i))  && | 
 | 246 | 				(shouldReport(stype, i, &index))) | 
 | 247 | 			{ | 
 | 248 | 				reportSensorEventAssert(pRec, index); | 
 | 249 | 			} | 
 | 250 | 			if ((ISBITSET(pRec->assert_state14_8,i))  && | 
 | 251 | 				(shouldReport(stype, i+8, &index))) | 
 | 252 | 			{ | 
 | 253 | 				reportSensorEventAssert(pRec, index); | 
 | 254 | 			} | 
 | 255 | 			if ((ISBITSET(pRec->deassert_state7_0,i))  && | 
 | 256 | 				(shouldReport(stype, i, &index))) | 
 | 257 | 			{ | 
 | 258 | 				reportSensorEventDeassert(pRec, index); | 
 | 259 | 			} | 
 | 260 | 			if ((ISBITSET(pRec->deassert_state14_8,i))  && | 
 | 261 | 				(shouldReport(stype, i+8, &index))) | 
 | 262 | 			{ | 
 | 263 | 				reportSensorEventDeassert(pRec, index); | 
 | 264 | 			} | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 265 | 		} | 
| Chris Austen | 0012e9b | 2015-10-22 01:37:46 -0500 | [diff] [blame] | 266 |  | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 267 | 	} | 
 | 268 |  | 
| Chris Austen | 0012e9b | 2015-10-22 01:37:46 -0500 | [diff] [blame] | 269 |  | 
| Chris Austen | 8a45e7c | 2015-10-15 00:31:46 -0500 | [diff] [blame] | 270 | 	return 0; | 
 | 271 | } |