Compare commits

...

8 commits

Author SHA1 Message Date
cinap_lenrek
ddaadd65b4 libdisk: cleanname() paths for setname()/mkpath(), avoid utfrrune() 2024-12-09 13:57:39 +00:00
cinap_lenrek
9d552b68e4 nusb/lib: decode classcode() 0xFF -> vendor, 0xFE -> application (-specific) 2024-12-09 13:00:16 +00:00
Ori Bernstein
8e2a071b8b acme/Mail: fix redrawn line offsets, add support for flag filters
maintaining ->nsub was fragile, and didn't save very many cycles;
instead just compute it every time; it's only going to hurt with
a ton of giant threads.
2024-12-09 05:27:05 +00:00
Ori Bernstein
af83b606f9 upas/Mail: Add support for message filtering 2024-12-09 03:58:40 +00:00
cinap_lenrek
aa1e68e9fe nusbrd: pass $usbdebug to nusb/usbd
This can be usefull for debugging usb enumeration issues from boot,
if one has the chance to pass parameters on the bootloader.

It was initially suggested in a troubleshooting session todo as
a quick modification, but it can be usefull in general.
2024-12-09 01:30:16 +00:00
cinap_lenrek
eb52c928b1 nusb/usbd: improve debugging, dont portfail() when port attaches/detaches too fast, cleanup
- always dprint() all the port state transitions.
- when port is attaching in short succession and we'r reaching the limit,
  don't return -1 as that would cause portfail(), return 1 instead
  which would make us ignore it.
- cleanup portattach(), use Dev *d instead of h->dev.
2024-12-08 01:10:41 +00:00
cinap_lenrek
8cc080311f nusb/lib: decode more base class codes in classname() 2024-12-07 15:55:12 +00:00
cinap_lenrek
eab5162760 nusb/audio: fix wrong emallocz() call in getclockrange() 2024-12-07 15:54:07 +00:00
9 changed files with 202 additions and 89 deletions

View file

@ -101,13 +101,26 @@ are listed in
.IR upasfs (4)
.PD 0
.TP
.B Filter [filter] [*flags]
Shows only messages where the sender or subject match
the
.I filter
regexp,
or where the
.I flags
string matches the state of the message. The flags
used are the same as for Mark, with the addition of
.I u
to represent unread messages.
Filter without an argument resets the filtering,
showing all messages again.
.PD 0
.TP
.B Redraw
Redraws the contents of the mailbox.
.PP
The following text commands are recognized by the message
view:
.TP
.B Reply [all]
Replies to a message, quoting it.
@ -120,15 +133,12 @@ As with the message view, but applied to the open message.
.TP
.B Mark
As with the message view, but applied to the open message.
.PP
The following text commands are recognized by the composition
window:
.TP
.B Post
Sends the message currently being composed.
.SS Format strings
The formatting of messages in the list view is controlled by the
format string defined through the

View file

@ -448,7 +448,7 @@ will appear when using the WIFI interface for netbooting.
To avoid the prompt, the
.I password
can be specified with the boot parameter above.
.SS \fLwpaopts=\fivalue\fP
.SS \fLwpaopts=\fIvalue\fP
Pass
.I value
as additional options to
@ -956,6 +956,14 @@ When defined,
.IR nusbrc (8)
will use the dynamically assigned usb device address to name
usb devices instead of the device unique name.
.SS \fLusbdebug=\fIvalue\fP
When defined, pass
.I value
as arguments to
.IR usbd (4).
Usually used to pass
.B -d
flags for verbose debug printing.
.SS VIDEO
.SS \fL*nocga=\fP
This inhibits the kernel and

View file

@ -5,7 +5,7 @@ if(! bind -a '#u' /dev)
mkdir -p -m 700 '#σc/usb'
mkdir -p -m 700 '#σc/usbnet'
if(! nusb/usbd)
if(! nusb/usbd $usbdebug)
exit
@{

View file

@ -266,17 +266,15 @@ parseasdesc1(Desc *dd, Aconf *c)
c->bits = b[4];
if(b[5] == 0){ /* continuous frequency range */
c->nfreq = 1;
c->freq = emallocz(sizeof(*f), 1);
c->freq->min = b[6] | b[7]<<8 | b[8]<<16;
c->freq->max = b[9] | b[10]<<8 | b[11]<<16;
c->freq = emallocz(sizeof(*f), 0);
c->freq->min = b[6] | (int)b[7]<<8 | (int)b[8]<<16;
c->freq->max = b[9] | (int)b[10]<<8 | (int)b[11]<<16;
} else { /* discrete sampling frequencies */
c->nfreq = b[5];
c->freq = emallocz(c->nfreq * sizeof(*f), 1);
c->freq = emallocz(c->nfreq * sizeof(*f), 0);
b += 6;
for(f = c->freq; f < c->freq+c->nfreq; f++, b += 3){
f->min = b[0] | b[1]<<8 | b[2]<<16;
f->max = f->min;
}
for(f = c->freq; f < c->freq+c->nfreq; f++, b += 3)
f->min = f->max = b[0] | (int)b[1]<<8 | (int)b[2]<<16;
}
break;
}
@ -356,8 +354,8 @@ getclockrange(Aconf *c)
werrstr("invalid response");
return -1;
}
c->freq = emallocz(n, sizeof(Range));
c->nfreq = n;
c->freq = emallocz(n*sizeof(Range), 0);
for(i = 0; i < n; i++)
c->freq[i] = (Range){GET4(&b[2 + i*12]), GET4(&b[6 + i*12])};
return 0;

View file

@ -9,8 +9,25 @@ static char *edir[] = {"in", "out", "inout"};
static char *etype[] = {"ctl", "iso", "bulk", "intr"};
static char* cnames[] =
{
"none", "audio", "comms", "hid", "",
"", "", "printer", "storage", "hub", "data"
[0x00] "none",
[0x01] "audio",
[0x02] "comms",
[0x03] "hid",
[0x05] "phys",
[0x06] "image",
[0x07] "printer",
[0x08] "storage",
[0x09] "hub",
[0x0A] "data",
[0x0B] "smartcard",
[0x0D] "drm",
[0x0E] "video",
[0x0F] "healthcare",
[0x10] "av",
[0x11] "billboard",
[0x12] "usbc",
[0x13] "display",
[0x14] "mctp",
};
static char* devstates[] =
{
@ -20,12 +37,25 @@ static char* devstates[] =
char*
classname(int c)
{
static char buf[30];
static char buf[12];
if(c >= 0 && c < nelem(cnames))
if(c >= 0 && c < nelem(cnames) && cnames[c] != nil && cnames[c][0] != '\0')
return cnames[c];
else{
seprint(buf, buf+30, "%d", c);
switch(c){
case 0x3C: /* I3C Device Class */
return "i3c";
case 0xDC: /* Diagnostic Device */
return "debug";
case 0xE0: /* Wireless Controller */
return "wireless";
case 0xEF: /* Miscellaneous */
return "misc";
case 0xFE: /* Application specific */
return "application";
case 0xFF: /* Vendor specific */
return "vendor";
default:
snprint(buf, sizeof(buf), "%d", c);
return buf;
}
}
@ -146,11 +176,9 @@ emallocz(ulong size, int zero)
{
void *x;
x = malloc(size);
x = mallocz(size, zero);
if(x == nil)
sysfatal("malloc: %r");
if(zero)
memset(x, 0, size);
setmalloctag(x, getcallerpc(&size));
return x;
}

View file

@ -419,17 +419,13 @@ getmaxpkt(Dev *d)
* BUG: does not consider max. power avail.
*/
static int
portattach(Hub *h, int p, u32int sts)
portattach(Hub *h, int p)
{
Dev *d;
Dev *nd, *d;
Port *pp;
Dev *nd;
char fname[80];
char buf[40];
char *sp;
int mp;
int nr;
int i;
char *sp, fname[80], buf[40];
int mp, nr, i;
u32int sts;
d = h->dev;
pp = &h->port[p];
@ -445,9 +441,11 @@ portattach(Hub *h, int p, u32int sts)
if(++pp->acount > Attachcount){
fprint(2, "%s: %s: port %d: too many attaches in short succession\n",
argv0, d->dir, p);
return -1;
/* don't call portfail() */
return 1;
}
if(h->dev->isusb3){
if(d->isusb3){
sts = pp->sts;
sp = "super";
} else {
if(portfeature(h, p, Fportreset, 1) < 0){
@ -463,12 +461,12 @@ portattach(Hub *h, int p, u32int sts)
if(sts & PShigh)
sp = "high";
}
dprint(2, "%s: %s: port %d: attached status %s %#ux, speed %s\n", argv0, d->dir, p,
stsstr(sts, d->isusb3), sts, sp);
if((sts & PSenable) == 0){
dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p);
return -1;
}
dprint(2, "%s: %s: port %d: attached status %s %#ux, speed %s\n", argv0, d->dir, p,
stsstr(sts, h->dev->isusb3), sts, sp);
pp->sts = sts;
pp->state = Pattached;
if(devctl(d, "newdev %s %d", sp, p) < 0){
@ -490,8 +488,8 @@ portattach(Hub *h, int p, u32int sts)
return -1;
}
pp->dev = nd;
nd->depth = h->dev->depth+1;
nd->isusb3 = h->dev->isusb3;
nd->depth = d->depth+1;
nd->isusb3 = d->isusb3;
if(usbdebug > 2)
devctl(nd, "debug 1");
for(i=1;; i++){
@ -659,6 +657,11 @@ enumhub(Hub *h, int p)
}
onhubs = nhubs;
pp = &h->port[p];
if(sts != pp->sts){
dprint(2, "%s: %s port %d: sts %s %#ux ->", argv0, d->dir, p,
stsstr(pp->sts, d->isusb3), pp->sts);
dprint(2, " %s %#ux\n", stsstr(sts, d->isusb3), sts);
}
if((sts & PSpresent) == 0 && (pp->sts & PSpresent) != 0){
pp->sts = sts;
portdetach(h, p);
@ -670,17 +673,14 @@ enumhub(Hub *h, int p)
portfail(h, p, "reset");
} else if((sts & PSpresent) != 0 && (pp->sts & PSpresent) == 0){
pp->sts = sts;
if(portattach(h, p, sts) < 0){
if(portattach(h, p) < 0){
if(h->failed)
return -1;
if(pp->state != Pdisabled)
pp->sts = 0; /* force re-attach */
portfail(h, p, "attach");
}
} else if(sts != pp->sts){
dprint(2, "%s: %s port %d: sts %s %#ux ->", argv0, d->dir, p,
stsstr(pp->sts, d->isusb3), pp->sts);
dprint(2, " %s %#ux\n", stsstr(sts, d->isusb3), sts);
} else {
pp->sts = sts;
}
return onhubs != nhubs;

View file

@ -16,6 +16,7 @@ enum {
Stoplev = 1<<1, /* not a response to anything */
Sopen = 1<<2, /* opened for viewing */
Szap = 1<<3, /* flushed, to be removed from list */
Shide = 1<<4, /* hidden from view */
};
enum {
@ -95,7 +96,6 @@ struct Mesg {
Mesg *parent;
Mesg **child;
int nchild;
int nsub; /* transitive children */
Mesg *body; /* best attachment to use, or nil */
Mesg **parts;

View file

@ -31,6 +31,8 @@ char *listfmt = "%>48s\t<%f>";
Mesg dead = {.messageid="", .hash=42};
Reprog *mesgpat;
Reprog *filterpat;
char *filterflags;
int threadsort = 1;
int sender;
@ -124,6 +126,45 @@ rcmpmesg(void *pa, void *pb)
return a->time - b->time;
}
static int
matchfilter(Mesg *m)
{
char *p;
int ok;
ok = 1;
if(filterpat != nil
&& m->subject != nil
&& m->from != nil){
if(!regexec(filterpat, m->subject, nil, 0)
&& !regexec(filterpat, m->from, nil, 0))
ok = 0;
}
for(p = filterflags; p && *p; p++){
switch(*p){
case 's': ok = ok && (m->flags & Fseen); break;
case 'u': ok = ok && !(m->flags & Fseen); break;
case 'a': ok = ok && (m->flags & Fresp); break;
}
}
return ok;
}
static int
nsub(Mesg *m)
{
Mesg *c;
int n, i;
n = 0;
for(i = 0; i < m->nchild; i++){
c = m->child[i];
if(!(c->state & (Sdummy|Shide)))
n += nsub(c)+1;
}
return n;
}
static int
mesglineno(Mesg *msg, int *depth)
{
@ -142,9 +183,9 @@ mesglineno(Mesg *msg, int *depth)
for(i = 0; i < p->nchild; i++){
if(p->child[i] == m)
break;
o += p->child[i]->nsub + 1;
o += nsub(p->child[i]) + 1;
}
if(!(p->state & (Sdummy|Szap))){
if(!(p->state & (Sdummy|Shide))){
o++;
d++;
}
@ -156,8 +197,8 @@ mesglineno(Mesg *msg, int *depth)
if(m == p)
break;
if(m->state & Stoplev){
n += mbox.mesg[i]->nsub;
if(!(m->state & (Sdummy|Szap)))
n += nsub(mbox.mesg[i]);
if(!(m->state & (Sdummy|Szap|Shide)))
n++;
}
@ -169,7 +210,7 @@ mesglineno(Mesg *msg, int *depth)
}
static int
addchild(Mesg *p, Mesg *m, int d)
addchild(Mesg *p, Mesg *m)
{
Mesg *q;
@ -181,8 +222,6 @@ addchild(Mesg *p, Mesg *m, int d)
if(m->time > q->time)
q->time = m->time;
}
for(q = p; q != nil; q = q->parent)
q->nsub += d;
p->child = erealloc(p->child, ++p->nchild*sizeof(Mesg*));
p->child[p->nchild - 1] = m;
qsort(p->child, p->nchild, sizeof(Mesg*), rcmpmesg);
@ -346,7 +385,6 @@ static Mesg*
load(char *name, char *digest, int ins)
{
Mesg *m, *p;
int d;
if(strncmp(name, mbox.path, strlen(mbox.path)) == 0)
name += strlen(mbox.path);
@ -356,13 +394,10 @@ load(char *name, char *digest, int ins)
if(digest != nil && strcmp(digest, m->digest) != 0)
goto error;
/* if we already have a dummy, populate it */
d = 1;
p = lookupid(m->messageid);
if(p != nil && (p->state & Sdummy)){
d = p->nsub + 1;
m->child = p->child;
m->nchild = p->nchild;
m->nsub = p->nsub;
mesgclear(p);
memcpy(p, m, sizeof(*p));
free(m);
@ -386,8 +421,10 @@ load(char *name, char *digest, int ins)
p = lookupid(m->inreplyto);
if(p == nil)
p = placeholder(m->inreplyto, m->time, ins);
if(!addchild(p, m, d))
if(!addchild(p, m))
m->state |= Stoplev;
if(!matchfilter(m))
m->state |= Shide;
return m;
error:
mesgfree(m);
@ -575,13 +612,12 @@ fmtmesg(Biobuf *bp, char *fmt, Mesg *m, int depth)
Bputc(bp, '\n');
}
static void
showmesg(Biobuf *bfd, Mesg *m, int depth, int recurse)
{
int i;
if(!(m->state & Sdummy)){
if(!(m->state & (Sdummy|Shide))){
fmtmesg(bfd, listfmt, m, depth);
depth++;
}
@ -654,7 +690,7 @@ mbmark(char **f, int nf)
static void
relinkmsg(Mesg *p, Mesg *m)
{
Mesg *c, *pp;
Mesg *c;
int i, j;
/* remove child, preserving order */
@ -664,14 +700,12 @@ relinkmsg(Mesg *p, Mesg *m)
p->child[j++] = p->child[i];
}
p->nchild = j;
for(pp = p; pp != nil; pp = pp->parent)
pp->nsub -= m->nsub + 1;
/* reparent children */
for(i = 0; i < m->nchild; i++){
c = m->child[i];
c->parent = nil;
addchild(p, c, c->nsub + 1);
addchild(p, c);
}
}
@ -694,17 +728,15 @@ mbflush(char **, int)
continue;
ln = mesglineno(m, nil);
fprint(mbox.addr, "%d,%d", ln, ln+m->nsub);
fprint(mbox.addr, "%d,%d", ln, ln+nsub(m));
write(mbox.data, "", 0);
if(m->flags & Ftodel)
fprint(fd, "delete %s %d", mailbox, atoi(m->name));
removeid(m);
m->state |= Szap;
if(p == nil && m->nsub != 0){
if(p == nil && nsub(m) != 0)
p = placeholder(m->messageid, m->time, 1);
p->nsub = m->nsub + 1;
}
if(p != nil)
relinkmsg(p, m);
for(j = 0; j < m->nchild; j++)
@ -814,10 +846,10 @@ changemesg(Plumbmsg *pm)
for(r = m; r->parent != nil; r = r->parent)
/* nothing */;
/* Bump whole thread up in list */
if(r->nsub > 0){
if(nsub(r) > 0){
ln = mesglineno(r, nil);
nr = r->nsub-1;
if(!(r->state & Sdummy))
nr = nsub(r)-1;
if(!(r->state & (Sdummy|Shide)))
nr++;
/*
* We can end up with an empty container
@ -868,6 +900,46 @@ redraw(char **, int)
showlist();
}
static void
filter(char **filt, int nfilt)
{
Mesg *m;
int i;
if(nfilt > 2){
Usage:
fprint(2, "usage: Filter [regexp] [*flags]");
return;
}
free(filterpat);
free(filterflags);
filterpat = nil;
filterflags = nil;
for(i = 0; i < nfilt; i++){
if(*filt[i] == '*'){
if(filterflags != nil)
goto Usage;
filterflags = strdup(filt[i]+1);
}else{
if(filterpat != nil)
goto Usage;
filterpat = regcomp(filt[i]);
if(filterpat == nil){
fprint(2, "recomp: %r");
return;
}
}
}
for(i = 0; i < mbox.nmesg; i++){
m = mbox.mesg[i];
m->state &= ~Shide;
if(!matchfilter(m))
m->state |= Shide;
}
fprint(mbox.addr, ",");
showlist();
}
static void
nextunread(char **, int)
{
@ -886,8 +958,8 @@ Fn mboxfn[] = {
{"Redraw", redraw},
{"Next", nextunread},
{"Mark", mbmark},
#ifdef NOTYET
{"Filter", filter},
#ifdef NOTYET
{"Get", mbrefresh},
#endif
{nil}

View file

@ -229,8 +229,8 @@ enum {
static void
setname(Mkaux *mkaux, Name *name, File *f)
{
char *s1, *s2, *ss;
int l;
char *s1, *s2;
int n;
s1 = mkaux->root;
s2 = "";
@ -242,18 +242,14 @@ setname(Mkaux *mkaux, Name *name, File *f)
s2 = f->old;
}else
s2 = f->new;
l = strlen(s1);
ss = (*s1 && *s2 && *s2 != '/' && s1[l-1] != '/') ? "/" : "";
l += strlen(ss);
l += strlen(s2);
l++;
if(name->n < l+SLOP/2) {
n = strlen(s1) + strlen(s2) + 2;
if(name->n < n+SLOP/2) {
free(name->s);
name->s = emalloc(mkaux, l+SLOP);
name->n = l+SLOP;
name->s = emalloc(mkaux, n+SLOP);
name->n = n+SLOP;
}
snprint(name->s, name->n, "%s%s%s", s1, ss, s2);
snprint(name->s, name->n, "%s/%s", s1, s2);
cleanname(name->s);
}
@ -311,10 +307,8 @@ mkpath(Mkaux *mkaux, char *prefix, char *elem)
n = strlen(prefix) + strlen(elem) + 2;
p = emalloc(mkaux, n);
strcpy(p, prefix);
strcat(p, "/");
strcat(p, elem);
return p;
snprint(p, n, "%s/%s", prefix, elem);
return cleanname(p);
}
static int
@ -552,8 +546,11 @@ loop:
f = emalloc(mkaux, sizeof *f);
f->new = mkpath(mkaux, old->new, elem);
if((s = strrchr(f->new, '/')) != nil)
f->elem = s+1;
else
f->elem = f->new;
free(elem);
f->elem = utfrrune(f->new, L'/') + 1;
if((p = getmode(mkaux, p, &f->mode)) == nil){
freefile(f);