PLDHashOperator pref_savePref(PLDHashTable *table, PLDHashEntryHdr *heh, PRUint32 i, void *arg) { pref_saveArgs *argData = static_cast<pref_saveArgs *>(arg); PrefHashEntry *pref = static_cast<PrefHashEntry *>(heh); PR_ASSERT(pref); if (!pref) return PL_DHASH_NEXT; nsCAutoString prefValue; nsCAutoString prefPrefix; prefPrefix.Assign(NS_LITERAL_CSTRING("user_pref(\"")); // where we're getting our pref from PrefValue* sourcePref; if (PREF_HAS_USER_VALUE(pref) && pref_ValueChanged(pref->defaultPref, pref->userPref, (PrefType) PREF_TYPE(pref))) { sourcePref = &pref->userPref; } else { if (argData->saveTypes == SAVE_ALL_AND_DEFAULTS) { prefPrefix.Assign(NS_LITERAL_CSTRING("pref(\"")); sourcePref = &pref->defaultPref; } else // do not save default prefs that haven't changed return PL_DHASH_NEXT; } // strings are in quotes! if (pref->flags & PREF_STRING) { prefValue = '\"'; str_escape(sourcePref->stringVal, prefValue); prefValue += '\"'; } else if (pref->flags & PREF_INT) prefValue.AppendInt(sourcePref->intVal); else if (pref->flags & PREF_BOOL) prefValue = (sourcePref->boolVal) ? "true" : "false"; nsCAutoString prefName; str_escape(pref->key, prefName); argData->prefArray[i] = ToNewCString(prefPrefix + prefName + NS_LITERAL_CSTRING("\", ") + prefValue + NS_LITERAL_CSTRING(");")); return PL_DHASH_NEXT; }
/* * This is an abbreviated parser for the HID Report Descriptor. We * know what devices we are talking to, so this is by no means meant * to be generic. We can make some safe assumptions: * * - We know there are no LONG tags, all short * - We know that we have no MAIN Feature and MAIN Output items * - We know what the IRQ reports are supposed to look like. * * The main purpose of this is to use the HID report desc to figure * out the mins and maxs of the fields in the IRQ reports. The IRQ * reports for 400/401 change slightly if the max X is bigger than 64K. * */ static void parse_hid_report_descriptor(struct gtco *device, char * report, int length) { int x, i = 0; /* Tag primitive vars */ __u8 prefix; __u8 size; __u8 tag; __u8 type; __u8 data = 0; __u16 data16 = 0; __u32 data32 = 0; /* For parsing logic */ int inputnum = 0; __u32 usage = 0; /* Global Values, indexed by TAG */ __u32 globalval[TAG_GLOB_MAX]; __u32 oldval[TAG_GLOB_MAX] = {0}; /* Debug stuff */ char maintype = 'x'; char globtype[12]; int indent = 0; char indentstr[10] = ""; dbg("======>>>>>>PARSE<<<<<<======"); /* Walk this report and pull out the info we need */ while (i < length) { prefix = report[i]; /* Skip over prefix */ i++; /* Determine data size and save the data in the proper variable */ size = PREF_SIZE(prefix); switch (size) { case 1: data = report[i]; break; case 2: data16 = get_unaligned_le16(&report[i]); break; case 3: size = 4; data32 = get_unaligned_le32(&report[i]); break; } /* Skip size of data */ i += size; /* What we do depends on the tag type */ tag = PREF_TAG(prefix); type = PREF_TYPE(prefix); switch (type) { case TYPE_MAIN: strcpy(globtype, ""); switch (tag) { case TAG_MAIN_INPUT: /* * The INPUT MAIN tag signifies this is * information from a report. We need to * figure out what it is and store the * min/max values */ maintype = 'I'; if (data == 2) strcpy(globtype, "Variable"); else if (data == 3) strcpy(globtype, "Var|Const"); dbg("::::: Saving Report: %d input #%d Max: 0x%X(%d) Min:0x%X(%d) of %d bits", globalval[TAG_GLOB_REPORT_ID], inputnum, globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]); /* We can assume that the first two input items are always the X and Y coordinates. After that, we look for everything else by local usage value */ switch (inputnum) { case 0: /* X coord */ dbg("GER: X Usage: 0x%x", usage); if (device->max_X == 0) { device->max_X = globalval[TAG_GLOB_LOG_MAX]; device->min_X = globalval[TAG_GLOB_LOG_MIN]; } break; case 1: /* Y coord */ dbg("GER: Y Usage: 0x%x", usage); if (device->max_Y == 0) { device->max_Y = globalval[TAG_GLOB_LOG_MAX]; device->min_Y = globalval[TAG_GLOB_LOG_MIN]; } break; default: /* Tilt X */ if (usage == DIGITIZER_USAGE_TILT_X) { if (device->maxtilt_X == 0) { device->maxtilt_X = globalval[TAG_GLOB_LOG_MAX]; device->mintilt_X = globalval[TAG_GLOB_LOG_MIN]; } } /* Tilt Y */ if (usage == DIGITIZER_USAGE_TILT_Y) { if (device->maxtilt_Y == 0) { device->maxtilt_Y = globalval[TAG_GLOB_LOG_MAX]; device->mintilt_Y = globalval[TAG_GLOB_LOG_MIN]; } } /* Pressure */ if (usage == DIGITIZER_USAGE_TIP_PRESSURE) { if (device->maxpressure == 0) { device->maxpressure = globalval[TAG_GLOB_LOG_MAX]; device->minpressure = globalval[TAG_GLOB_LOG_MIN]; } } break; } inputnum++; break; case TAG_MAIN_OUTPUT: maintype = 'O'; break; case TAG_MAIN_FEATURE: maintype = 'F'; break; case TAG_MAIN_COL_START: maintype = 'S'; if (data == 0) { dbg("======>>>>>> Physical"); strcpy(globtype, "Physical"); } else dbg("======>>>>>>"); /* Indent the debug output */ indent++; for (x = 0; x < indent; x++) indentstr[x] = '-'; indentstr[x] = 0; /* Save global tags */ for (x = 0; x < TAG_GLOB_MAX; x++) oldval[x] = globalval[x]; break; case TAG_MAIN_COL_END: dbg("<<<<<<======"); maintype = 'E'; indent--; for (x = 0; x < indent; x++) indentstr[x] = '-'; indentstr[x] = 0; /* Copy global tags back */ for (x = 0; x < TAG_GLOB_MAX; x++) globalval[x] = oldval[x]; break; } switch (size) { case 1: dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", indentstr, tag, maintype, size, globtype, data); break; case 2: dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", indentstr, tag, maintype, size, globtype, data16); break; case 4: dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", indentstr, tag, maintype, size, globtype, data32); break; } break; case TYPE_GLOBAL: switch (tag) { case TAG_GLOB_USAGE: /* * First time we hit the global usage tag, * it should tell us the type of device */ if (device->usage == 0) device->usage = data; strcpy(globtype, "USAGE"); break; case TAG_GLOB_LOG_MIN: strcpy(globtype, "LOG_MIN"); break; case TAG_GLOB_LOG_MAX: strcpy(globtype, "LOG_MAX"); break; case TAG_GLOB_PHYS_MIN: strcpy(globtype, "PHYS_MIN"); break; case TAG_GLOB_PHYS_MAX: strcpy(globtype, "PHYS_MAX"); break; case TAG_GLOB_UNIT_EXP: strcpy(globtype, "EXP"); break; case TAG_GLOB_UNIT: strcpy(globtype, "UNIT"); break; case TAG_GLOB_REPORT_SZ: strcpy(globtype, "REPORT_SZ"); break; case TAG_GLOB_REPORT_ID: strcpy(globtype, "REPORT_ID"); /* New report, restart numbering */ inputnum = 0; break; case TAG_GLOB_REPORT_CNT: strcpy(globtype, "REPORT_CNT"); break; case TAG_GLOB_PUSH: strcpy(globtype, "PUSH"); break; case TAG_GLOB_POP: strcpy(globtype, "POP"); break; } /* Check to make sure we have a good tag number so we don't overflow array */ if (tag < TAG_GLOB_MAX) { switch (size) { case 1: dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", indentstr, globtype, tag, size, data); globalval[tag] = data; break; case 2: dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", indentstr, globtype, tag, size, data16); globalval[tag] = data16; break; case 4: dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", indentstr, globtype, tag, size, data32); globalval[tag] = data32; break; } } else { dbg("%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d ", indentstr, tag, size); } break; case TYPE_LOCAL: switch (tag) { case TAG_GLOB_USAGE: strcpy(globtype, "USAGE"); /* Always 1 byte */ usage = data; break; case TAG_GLOB_LOG_MIN: strcpy(globtype, "MIN"); break; case TAG_GLOB_LOG_MAX: strcpy(globtype, "MAX"); break; default: strcpy(globtype, "UNKNOWN"); break; } switch (size) { case 1: dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", indentstr, tag, globtype, size, data); break; case 2: dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", indentstr, tag, globtype, size, data16); break; case 4: dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", indentstr, tag, globtype, size, data32); break; } break; } } }
static void parse_hid_report_descriptor(struct gtco *device, char * report, int length) { int x, i = 0; __u8 prefix; __u8 size; __u8 tag; __u8 type; __u8 data = 0; __u16 data16 = 0; __u32 data32 = 0; int inputnum = 0; __u32 usage = 0; __u32 globalval[TAG_GLOB_MAX]; __u32 oldval[TAG_GLOB_MAX]; char maintype = 'x'; char globtype[12]; int indent = 0; char indentstr[10] = ""; dbg("======>>>>>>PARSE<<<<<<======"); while (i < length) { prefix = report[i]; i++; size = PREF_SIZE(prefix); switch (size) { case 1: data = report[i]; break; case 2: data16 = get_unaligned_le16(&report[i]); break; case 3: size = 4; data32 = get_unaligned_le32(&report[i]); break; } i += size; tag = PREF_TAG(prefix); type = PREF_TYPE(prefix); switch (type) { case TYPE_MAIN: strcpy(globtype, ""); switch (tag) { case TAG_MAIN_INPUT: maintype = 'I'; if (data == 2) strcpy(globtype, "Variable"); else if (data == 3) strcpy(globtype, "Var|Const"); dbg("::::: Saving Report: %d input #%d Max: 0x%X(%d) Min:0x%X(%d) of %d bits", globalval[TAG_GLOB_REPORT_ID], inputnum, globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]); switch (inputnum) { case 0: dbg("GER: X Usage: 0x%x", usage); if (device->max_X == 0) { device->max_X = globalval[TAG_GLOB_LOG_MAX]; device->min_X = globalval[TAG_GLOB_LOG_MIN]; } break; case 1: dbg("GER: Y Usage: 0x%x", usage); if (device->max_Y == 0) { device->max_Y = globalval[TAG_GLOB_LOG_MAX]; device->min_Y = globalval[TAG_GLOB_LOG_MIN]; } break; default: if (usage == DIGITIZER_USAGE_TILT_X) { if (device->maxtilt_X == 0) { device->maxtilt_X = globalval[TAG_GLOB_LOG_MAX]; device->mintilt_X = globalval[TAG_GLOB_LOG_MIN]; } } if (usage == DIGITIZER_USAGE_TILT_Y) { if (device->maxtilt_Y == 0) { device->maxtilt_Y = globalval[TAG_GLOB_LOG_MAX]; device->mintilt_Y = globalval[TAG_GLOB_LOG_MIN]; } } if (usage == DIGITIZER_USAGE_TIP_PRESSURE) { if (device->maxpressure == 0) { device->maxpressure = globalval[TAG_GLOB_LOG_MAX]; device->minpressure = globalval[TAG_GLOB_LOG_MIN]; } } break; } inputnum++; break; case TAG_MAIN_OUTPUT: maintype = 'O'; break; case TAG_MAIN_FEATURE: maintype = 'F'; break; case TAG_MAIN_COL_START: maintype = 'S'; if (data == 0) { dbg("======>>>>>> Physical"); strcpy(globtype, "Physical"); } else dbg("======>>>>>>"); indent++; for (x = 0; x < indent; x++) indentstr[x] = '-'; indentstr[x] = 0; for (x = 0; x < TAG_GLOB_MAX; x++) oldval[x] = globalval[x]; break; case TAG_MAIN_COL_END: dbg("<<<<<<======"); maintype = 'E'; indent--; for (x = 0; x < indent; x++) indentstr[x] = '-'; indentstr[x] = 0; for (x = 0; x < TAG_GLOB_MAX; x++) globalval[x] = oldval[x]; break; } switch (size) { case 1: dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", indentstr, tag, maintype, size, globtype, data); break; case 2: dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", indentstr, tag, maintype, size, globtype, data16); break; case 4: dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", indentstr, tag, maintype, size, globtype, data32); break; } break; case TYPE_GLOBAL: switch (tag) { case TAG_GLOB_USAGE: if (device->usage == 0) device->usage = data; strcpy(globtype, "USAGE"); break; case TAG_GLOB_LOG_MIN: strcpy(globtype, "LOG_MIN"); break; case TAG_GLOB_LOG_MAX: strcpy(globtype, "LOG_MAX"); break; case TAG_GLOB_PHYS_MIN: strcpy(globtype, "PHYS_MIN"); break; case TAG_GLOB_PHYS_MAX: strcpy(globtype, "PHYS_MAX"); break; case TAG_GLOB_UNIT_EXP: strcpy(globtype, "EXP"); break; case TAG_GLOB_UNIT: strcpy(globtype, "UNIT"); break; case TAG_GLOB_REPORT_SZ: strcpy(globtype, "REPORT_SZ"); break; case TAG_GLOB_REPORT_ID: strcpy(globtype, "REPORT_ID"); inputnum = 0; break; case TAG_GLOB_REPORT_CNT: strcpy(globtype, "REPORT_CNT"); break; case TAG_GLOB_PUSH: strcpy(globtype, "PUSH"); break; case TAG_GLOB_POP: strcpy(globtype, "POP"); break; } if (tag < TAG_GLOB_MAX) { switch (size) { case 1: dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", indentstr, globtype, tag, size, data); globalval[tag] = data; break; case 2: dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", indentstr, globtype, tag, size, data16); globalval[tag] = data16; break; case 4: dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", indentstr, globtype, tag, size, data32); globalval[tag] = data32; break; } } else { dbg("%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d ", indentstr, tag, size); } break; case TYPE_LOCAL: switch (tag) { case TAG_GLOB_USAGE: strcpy(globtype, "USAGE"); usage = data; break; case TAG_GLOB_LOG_MIN: strcpy(globtype, "MIN"); break; case TAG_GLOB_LOG_MAX: strcpy(globtype, "MAX"); break; default: strcpy(globtype, "UNKNOWN"); break; } switch (size) { case 1: dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", indentstr, tag, globtype, size, data); break; case 2: dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", indentstr, tag, globtype, size, data16); break; case 4: dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", indentstr, tag, globtype, size, data32); break; } break; } } }