Provide dev option -c*/u for udev rules

This commit is contained in:
Stefan Rueger
2024-08-04 20:35:09 +01:00
parent 7cc0e08b89
commit 192a34f2db
2 changed files with 111 additions and 6 deletions

View File

@@ -1381,8 +1381,9 @@ static void dev_pgm_strct(const PROGRAMMER *pgm, bool tsv, const PROGRAMMER *bas
for(int i=0; i<N_PINS; i++) {
const char *str = pins_to_str(pgm->pin+i);
const char *bstr = base? pins_to_str(base->pin+i): NULL;
if(!base || !str_eq(bstr, str))
_pgmout_fmt(avr_pin_lcname(i), "%s", str);
const char *pinname = avr_pin_lcname(i);
if((!base || !str_eq(bstr, str)) && !str_eq(pinname, "<unknown>"))
_pgmout_fmt(pinname, "%s", str);
}
pgmstr = dev_hvupdi_support_liststr(pgm);
@@ -1413,9 +1414,54 @@ static void dev_pgm_strct(const PROGRAMMER *pgm, bool tsv, const PROGRAMMER *bas
}
// -c <wildcard>/[dASsrtiBUPTIJWHQ]
typedef struct {
int vid, pid, ishid;
const char *ids;
} Dev_udev;
static Dev_udev *add_udev(Dev_udev *ud, int *uip, int vid, int pid, int ishid, const char *ids) {
for(int i = 0; i < *uip; i++) // Already entered?
if(ud[i].vid == vid && ud[i].pid == pid && ud[i].ishid == ishid && ud[i].ids == ids)
return ud;
if(*uip % 128 == 0)
ud = (Dev_udev *) mmt_realloc(ud, sizeof*ud*(*uip+128));
ud[*uip].vid = vid;
ud[*uip].pid = pid;
ud[*uip].ishid = ishid;
ud[*uip].ids = ids;
(*uip)++;
return ud;
}
static int udev_cmp_wout_ids(const Dev_udev *p1, const Dev_udev *p2) {
int diff;
if((diff = p1->vid - p2->vid))
return diff;
if((diff = p1->pid - p2->pid))
return diff;
return p1->ishid - p2->ishid;
}
static int udev_cmp(const void *v1, const void *v2) {
const Dev_udev *p1 = v1, *p2 = v2;
int diff;
if((diff = udev_cmp_wout_ids(p1, p2)))
return diff;
return strcmp(p1->ids, p2->ids);
}
#include "flip1.h"
#include "flip2.h"
#include "jtag3.h"
#include "stk500v2.h"
// -c <wildcard>/[duASsrtiBUPTIJWHQ]
void dev_output_pgm_defs(char *pgmidcp) {
bool descs, astrc, strct, cmpst, raw, tsv, injct;
bool descs, astrc, strct, cmpst, raw, tsv, injct, udev;
char *flags;
int nprinted;
PROGRAMMER *nullpgm = pgm_new();
@@ -1426,7 +1472,7 @@ void dev_output_pgm_defs(char *pgmidcp) {
if(!flags && str_eq(pgmidcp, "*")) // Treat -c * as if it was -c */s
flags = "s";
if(!*flags || !strchr("dASsrtiBUPTIJWHQ", *flags)) {
if(!*flags || !strchr("duASsrtiBUPTIJWHQ", *flags)) {
dev_info("Error: flags for developer option -c <wildcard>/<flags> not recognised\n");
dev_info(
"Wildcard examples (these need protecting in the shell through quoting):\n"
@@ -1436,6 +1482,7 @@ void dev_output_pgm_defs(char *pgmidcp) {
" jtag?pdi matches jtag2pdi and jtag3pdi\n"
"Flags (one or more of the characters below):\n"
" d description of core programmer features\n"
" u show udev entry for programmer\n"
" A show entries of avrdude.conf programmers with all values\n"
" S show entries of avrdude.conf programmers with necessary values\n"
" s show short entries of avrdude.conf programmers using parent\n"
@@ -1465,9 +1512,13 @@ void dev_output_pgm_defs(char *pgmidcp) {
raw = !!strchr(flags, 'r');
tsv = !!strchr(flags, 't');
injct = !!strchr(flags, 'i');
udev = !!strchr(flags, 'u');
nprinted = dev_nprinted;
int ui = 0;
Dev_udev *udr = NULL;
LNODEID ln1, ln2;
for(ln1=lfirst(programmers); ln1; ln1=lnext(ln1)) {
PROGRAMMER *pgm = ldata(ln1);
@@ -1480,6 +1531,7 @@ void dev_output_pgm_defs(char *pgmidcp) {
}
if(!matched)
continue;
if(!prog_modes_in_flags(pgm->prog_modes, flags))
continue;
@@ -1508,7 +1560,60 @@ void dev_output_pgm_defs(char *pgmidcp) {
);
}
if(udev && pgm->usbpid && (pgm->conntype == CONNTYPE_USB || is_serialadapter(pgm))) {
void (* pi)(PROGRAMMER *) = pgm->initpgm;
const char *ids = cache_string(str_ccpgmids(pgm->id));
int usbvid = pgm->usbvid, ishid =
pi == jtag3_initpgm || pi == jtag3_pdi_initpgm || pi == jtag3_updi_initpgm ||
pi == jtag3_dw_initpgm || pi == stk500v2_jtag3_initpgm || pi == jtag3_tpi_initpgm;
if(!lfirst(pgm->usbpid)) {
if(pi == flip1_initpgm || pi == flip2_initpgm) { // Bootloaders, add possible part pids
for(LNODEID lp = lfirst(part_list); lp; lp = lnext(lp)) {
AVRPART *pt = ldata(lp);
if(pt->usbpid)
udr = add_udev(udr, &ui, usbvid, pt->usbpid, 0, ids);
}
}
}
for(LNODEID pidn=lfirst(pgm->usbpid); pidn; pidn=lnext(pidn))
udr = add_udev(udr, &ui, usbvid, *(int *) ldata(pidn), ishid, ids);
}
if(raw)
dev_pgm_raw(pgm);
}
if(udev && ui) {
dev_info("# 1. Put Linux udev rules into /etc/udev/rules.d/80-avrdude.rules (or similar)\n");
dev_info("# 2. sudo udevadm control --reload-rules && sudo udevadm trigger (or similar)\n");
dev_info("# 3. Unplug the device and plug it in again\n");
qsort(udr, ui, sizeof *udr, udev_cmp);
char *prev_head = mmt_strdup("<none>");
for(Dev_udev *u = udr; u-udr < ui; u++) {
char head[1024] = {0}, *h = head;
strncpy(h, u->ids, sizeof head - 1), h += strlen(h);
for(Dev_udev *v = u+1; v-udr < ui; v++) {
if(udev_cmp_wout_ids(u, v))
break;
if((int) (strlen(v->ids) + 3 + h-head) <= (int) sizeof head) {
strcpy(h, ", "), h += 2;
strcpy(h, v->ids), h += strlen(v->ids);
}
u = v;
}
if(!str_eq(prev_head, head)) {
dev_info("\n# %s\n", head);
mmt_free(prev_head);
prev_head = mmt_strdup(head);
}
dev_info("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", "
"GROUP=\"plugdev\", MODE=\"0660\", TAG+=\"uaccess\"\n", u->vid, u->pid);
if(u->ishid)
dev_info("KERNEL==\"hidraw*\", SUBSYSTEM==\"hidraw\", ATTRS{idVendor}==\"%04x\", "
"ATTRS{idProduct}==\"%04x\", GROUP=\"plugdev\", MODE=\"0660\", TAG+=\"uaccess\"\n", u->vid, u->pid);
}
mmt_free(prev_head);
}
}

View File

@@ -1123,7 +1123,7 @@ int main(int argc, char * argv [])
pgmid = cache_string(default_programmer);
// Developer options to print parts and/or programmer entries of avrdude.conf
int dev_opt_c = dev_opt(pgmid); // -c <wildcard>/[dASsrtiBUPTIJWHQ]
int dev_opt_c = dev_opt(pgmid); // -c <wildcard>/[duASsrtiBUPTIJWHQ]
int dev_opt_p = dev_opt(partdesc); // -p <wildcard>/[cdoASsrw*tiBUPTIJWHQ]
if(dev_opt_c || dev_opt_p) { // See -c/h and or -p/h