|
Lines 62-67
Link Here
|
| 62 |
#define USB_DEV_QUIRKS_MAX 384 |
62 |
#define USB_DEV_QUIRKS_MAX 384 |
| 63 |
#define USB_SUB_QUIRKS_MAX 8 |
63 |
#define USB_SUB_QUIRKS_MAX 8 |
| 64 |
|
64 |
|
|
|
65 |
#define ENVNAMEROOT "usb.quirk." |
| 66 |
|
| 65 |
struct usb_quirk_entry { |
67 |
struct usb_quirk_entry { |
| 66 |
uint16_t vid; |
68 |
uint16_t vid; |
| 67 |
uint16_t pid; |
69 |
uint16_t pid; |
|
Lines 612-617
Link Here
|
| 612 |
} |
614 |
} |
| 613 |
|
615 |
|
| 614 |
/*------------------------------------------------------------------------* |
616 |
/*------------------------------------------------------------------------* |
|
|
617 |
* usb_quirk_str2num |
| 618 |
* |
| 619 |
* This function converts an USB quirk string into its code. |
| 620 |
* |
| 621 |
* Returns: |
| 622 |
* -1: Quirk not found |
| 623 |
* Else: Quirk code |
| 624 |
*------------------------------------------------------------------------*/ |
| 625 |
static int32_t |
| 626 |
usb_quirk_str2num(char *name, int32_t namelen) |
| 627 |
{ |
| 628 |
int i; |
| 629 |
|
| 630 |
for (i = 0; i < USB_QUIRK_MAX; i++) { |
| 631 |
if (usb_quirk_str[i] != NULL |
| 632 |
&& strncmp(name, usb_quirk_str[i], namelen) == 0 |
| 633 |
&& usb_quirk_str[i][namelen] == '\0') |
| 634 |
return i; |
| 635 |
} |
| 636 |
|
| 637 |
return -1; |
| 638 |
} |
| 639 |
|
| 640 |
/*------------------------------------------------------------------------* |
| 615 |
* usb_test_quirk_by_info |
641 |
* usb_test_quirk_by_info |
| 616 |
* |
642 |
* |
| 617 |
* Returns: |
643 |
* Returns: |
|
Lines 853-867
Link Here
|
| 853 |
return (ENOIOCTL); |
879 |
return (ENOIOCTL); |
| 854 |
} |
880 |
} |
| 855 |
|
881 |
|
|
|
882 |
/*------------------------------------------------------------------------* |
| 883 |
* usb_quirk_add_entry_from_str |
| 884 |
* |
| 885 |
* Add a USB quirk entry from string. |
| 886 |
* "VENDOR PRODUCT LO_REV HI_REV QUIRK[,QUIRK[,...]]" |
| 887 |
*------------------------------------------------------------------------*/ |
| 888 |
static void |
| 889 |
usb_quirk_add_entry_from_str(char *name, char *env) |
| 890 |
{ |
| 891 |
struct usb_quirk_entry entry = { 0 }, *new; |
| 892 |
int32_t quirk; |
| 893 |
uint32_t quirk_idx; |
| 894 |
char *end; |
| 895 |
|
| 896 |
entry.vid = (uint16_t)strtoul(env, &end, 0); |
| 897 |
if (env == end || *end != ' ') { |
| 898 |
if (*end == '\0') |
| 899 |
goto too_short; |
| 900 |
printf("%s: invalid USB quirk vendor ID at \"%s\"\n", |
| 901 |
name, env); |
| 902 |
return; |
| 903 |
} |
| 904 |
|
| 905 |
env = end + 1; |
| 906 |
entry.pid = (uint16_t)strtoul(env, &end, 0); |
| 907 |
if (env == end || *end != ' ') { |
| 908 |
if (*end == '\0') |
| 909 |
goto too_short; |
| 910 |
printf("%s: invalid USB quirk product ID at \"%s\"\n", |
| 911 |
name, env); |
| 912 |
return; |
| 913 |
} |
| 914 |
|
| 915 |
env = end + 1; |
| 916 |
entry.lo_rev = (uint16_t)strtoul(env, &end, 0); |
| 917 |
if (env == end || *end != ' ') { |
| 918 |
if (*end == '\0') |
| 919 |
goto too_short; |
| 920 |
printf("%s: invalid USB quirk low revision at \"%s\"\n", |
| 921 |
name, env); |
| 922 |
return; |
| 923 |
} |
| 924 |
|
| 925 |
env = end + 1; |
| 926 |
entry.hi_rev = (uint16_t)strtoul(env, &end, 0); |
| 927 |
if (env == end || *end != ' ') { |
| 928 |
if (*end == '\0') |
| 929 |
goto too_short; |
| 930 |
printf("%s: invalid USB quirk high revision at \"%s\"\n", |
| 931 |
name, env); |
| 932 |
return; |
| 933 |
} |
| 934 |
|
| 935 |
for (env = end; *++env == ' '; ) |
| 936 |
; /* nothing */ |
| 937 |
if (*env == '\0') { |
| 938 |
too_short: |
| 939 |
printf("%s: USB quirk definition not complete!\n", name); |
| 940 |
return; |
| 941 |
} |
| 942 |
|
| 943 |
for (quirk_idx = 0; quirk_idx < USB_SUB_QUIRKS_MAX; quirk_idx++) { |
| 944 |
end = strchr(env, ','); |
| 945 |
if (end == NULL) |
| 946 |
end = env + strlen(env); |
| 947 |
|
| 948 |
quirk = usb_quirk_str2num(env, end - env); |
| 949 |
if (quirk < 0) { |
| 950 |
printf("%s: unknown USB quirk \"%.*s\"\n", |
| 951 |
name, (int)(end - env), env); |
| 952 |
return; |
| 953 |
} |
| 954 |
|
| 955 |
entry.quirks[quirk_idx] = quirk; |
| 956 |
|
| 957 |
if (*end == '\0') { |
| 958 |
mtx_lock(&usb_quirk_mtx); |
| 959 |
new = usb_quirk_get_entry(entry.vid, entry.pid, |
| 960 |
entry.lo_rev, entry.hi_rev, 1); |
| 961 |
if (new == NULL) { |
| 962 |
mtx_unlock(&usb_quirk_mtx); |
| 963 |
printf("%s: USB quirks table full!\n", name); |
| 964 |
return; |
| 965 |
} |
| 966 |
bcopy(entry.quirks, new->quirks, sizeof(entry.quirks)); |
| 967 |
mtx_unlock(&usb_quirk_mtx); |
| 968 |
return; |
| 969 |
} |
| 970 |
|
| 971 |
env = end + 1; |
| 972 |
} |
| 973 |
|
| 974 |
printf("%s: too many usb quirks, only %d allowed!\n", |
| 975 |
name, USB_SUB_QUIRKS_MAX); |
| 976 |
} |
| 977 |
|
| 856 |
static void |
978 |
static void |
| 857 |
usb_quirk_init(void *arg) |
979 |
usb_quirk_init(void *arg) |
| 858 |
{ |
980 |
{ |
|
|
981 |
char envkey[sizeof(ENVNAMEROOT) + 2]; /* 2 digits max, 0 to 99 */ |
| 982 |
int i; |
| 983 |
|
| 859 |
/* initialize mutex */ |
984 |
/* initialize mutex */ |
| 860 |
mtx_init(&usb_quirk_mtx, "USB quirk", NULL, MTX_DEF); |
985 |
mtx_init(&usb_quirk_mtx, "USB quirk", NULL, MTX_DEF); |
| 861 |
|
986 |
|
| 862 |
/* register our function */ |
987 |
/* register our function */ |
| 863 |
usb_test_quirk_p = &usb_test_quirk_by_info; |
988 |
usb_test_quirk_p = &usb_test_quirk_by_info; |
| 864 |
usb_quirk_ioctl_p = &usb_quirk_ioctl; |
989 |
usb_quirk_ioctl_p = &usb_quirk_ioctl; |
|
|
990 |
|
| 991 |
for (i = 0; i < 100; i++) { |
| 992 |
snprintf(envkey, sizeof(envkey), ENVNAMEROOT "%d", i); |
| 993 |
|
| 994 |
if (!testenv(envkey)) |
| 995 |
break; /* Stop at first undefined var */ |
| 996 |
|
| 997 |
usb_quirk_add_entry_from_str(envkey, getenv(envkey)); |
| 998 |
} |
| 865 |
} |
999 |
} |
| 866 |
|
1000 |
|
| 867 |
static void |
1001 |
static void |