shithub: riscv

Download patch

ref: e2f0077935e5f588f555061feb99ec651f80b45b
parent: 9194371eac8f5fe192a9a8192a825eaeffb2d24d
author: glenda <[email protected]>
date: Fri Sep 2 15:25:17 EDT 2011

ptp: screw interrupts, use GetPartialObject to make rpcs shorter so it doesnt matter when we flush

--- a/sys/src/cmd/nusb/ptp/ptp.c
+++ b/sys/src/cmd/nusb/ptp/ptp.c
@@ -32,11 +32,13 @@
 	GetObject			=	0x1009,
 	GetThumb		=	0x100A,
 	DeleteObject		=	0x100B,
+	GetPartialObject	=	0x101B,
+
+	Maxio			=	0x2000,
 };
 
 typedef struct Ptprpc Ptprpc;
 typedef struct Node Node;
-typedef struct Ioflush Ioflush;
 
 struct Ptprpc
 {
@@ -46,7 +48,7 @@
 	uchar	transid[4];
 	union {
 		uchar	p[5][4];
-		uchar	d[500];
+		uchar	d[52];
 	};
 };
 
@@ -66,25 +68,20 @@
 	int		ndata;
 };
 
-struct Ioflush
-{
-	Channel	*c;
-	Ioproc	*io;
-};
-
-
 enum {
 	In,
 	Out,
+	Int,
+	Setup,
 };
 
-static Dev *usbep[2];
+static Dev *usbep[Setup+1];
 
-static int debug;
+static int debug = 0;
 static ulong time0;
 static int maxpacket = 64;
-static int sessionId = 0;
-static int transId = 0;
+static int sessionId = 1;
+static int transId = 1;
 
 static Node **nodes;
 static int nnodes;
@@ -233,7 +230,6 @@
 	}
 	if(debug)
 		hexdump("req>", (uchar*)&rpc, n);
-
 	werrstr("");
 	if(iowrite(io, usbep[Out]->dfd, &rpc, n) != n){
 		wasinterrupt();
@@ -267,10 +263,13 @@
 			wasinterrupt();
 			return -1;
 		}
-		while(p < e){	
-			if((n = iowrite(io, usbep[Out]->dfd, p, e-p)) < 0){
-				if(!wasinterrupt())
-					return -1;
+		while(p < e){
+			n = e - p;
+			if(n > Maxio)
+				n = Maxio;
+			if((n = iowrite(io, usbep[Out]->dfd, p, n)) < 0){
+				wasinterrupt();
+				return -1;
 			}
 			p += n;
 		}
@@ -286,55 +285,70 @@
 		*prdata = nil;
 		*prdatalen = 0;
 
-		do{
-			if((n = ioread(io, usbep[In]->dfd, &rpc, sizeof(rpc))) < 0){
+		while((n = ioread(io, usbep[In]->dfd, &rpc, sizeof(rpc))) <= 0){
+			if(n < 0){
 				wasinterrupt();
 				return -1;
 			}
-			if(debug)
-				hexdump("data<", (uchar*)&rpc, n);
-			if((l = ptpcheckerr(&rpc, 2, t, n)) < 0)
-				return -1;
-		} while(l);
-
-		l = GET4(rpc.length);
-		if((l < 4+2+2+4) || (l < n)){
-			werrstr("invalid recvdata length");
-			return -1;
 		}
+		if((l = ptpcheckerr(&rpc, 2, t, n)) < 0)
+			return -1;
+		if(l && GET2(rpc.type) == 3)
+			goto Resp1;
 
+		l = GET4(rpc.length);
 		l -= (4+2+2+4);
 		n -= (4+2+2+4);
-
+	
 		b = emalloc9p(l);
 		p = b;
 		e = b+l;
-		memmove(p, rpc.d, n);
-		p += n;
-
-		while(p < e){
-			if((n = ioread(io, usbep[In]->dfd, p, e-p)) < 0){
-				wasinterrupt();
-				free(b);
-				return -1;
-			}
+		if(n <= l){
+			if(debug)
+				hexdump("data<", rpc.d, n);
+			memmove(p, rpc.d, n);
 			p += n;
+			while(p < e){
+				n = e-p;
+				if(n > Maxio)
+					n = Maxio;
+				while((n = ioread(io, usbep[In]->dfd, p, n)) <= 0){
+					if(n < 0){
+						wasinterrupt();
+						free(b);
+						return -1;
+					}
+				}
+				if(debug)
+					hexdump("data<", p, n);
+				p += n;
+			}
+			*prdata = b;
+			*prdatalen = e-b;
+		} else {
+			if(debug)
+				hexdump("data<", rpc.d, l);
+			memmove(p, rpc.d, l);
+			*prdata = b;
+			*prdatalen = e-b;
+
+			n -= l;
+			memmove(&rpc, rpc.d+l, n);
+			goto Resp1;
 		}
-		*prdata = b;
-		*prdatalen =  e-b;
 	}
 
-	do {
-		if((n = ioread(io, usbep[In]->dfd, &rpc, sizeof(rpc))) < 0){
+	while((n = ioread(io, usbep[In]->dfd, &rpc, sizeof(rpc))) <= 0){
+		if(n < 0){
 			wasinterrupt();
 			return -1;
 		}
-		if(debug)
-			hexdump("resp<", (uchar*)&rpc, n);
-		if((l = ptpcheckerr(&rpc, 3, t, n)) < 0)
-			return -1;
-	} while(l);
-
+	}
+Resp1:
+	if(debug)
+		hexdump("resp<", (uchar*)&rpc, n);
+	if(ptpcheckerr(&rpc, 3, t, n))
+		return -1;
 	if(flags & OutParam){
 		int *pp;
 
@@ -347,48 +361,39 @@
 	return 0;
 }
 
-static void
-ioflusher(void *aux)
-{
-	Ioflush f = *((Ioflush*)aux);
-	while(recvp(f.c))
-		iointerrupt(f.io);
-	chanfree(f.c);
-}
-
 static int
 ptprpc(Req *r, int code, int flags, ...)
 {
 	va_list va;
-	Ioflush f;
+	Channel *c;
+	Ioproc *io;
 	Alt a[3];
 	char *m;
 	int i;
 
 	i = -1;
-	f.c = nil;
-	f.io = nil;
+	c = nil;
+	io = nil;
 	m = Einterrupt;
 	a[0].op = CHANRCV;
 	a[0].c = iochan;
-	a[0].v = &f.io;
+	a[0].v = &io;
 	if(r){
-		f.c = chancreate(sizeof(char*), 0);
+		c = chancreate(sizeof(char*), 0);
 		a[1].op = CHANRCV;
-		a[1].c = f.c;
+		a[1].c = c;
 		a[1].v = &m;
 		a[2].op = CHANEND;
-		r->aux = f.c;
+		r->aux = c;
 		srvrelease(r->srv);
 	} else
 		a[1].op = CHANEND;
 	if(alt(a) == 0){
-		ioflush(f.io);
-		if(f.c)
-			threadcreate(ioflusher, &f, 4*1024);
 		va_start(va, flags);
-		i = vptprpc(f.io, code, flags, va);
+		i = vptprpc(io, code, flags, va);
 		va_end(va);
+		if(i < 0 && debug)
+			fprint(2, "rpc: %r\n");
 	} else
 		werrstr("%s", m);
 	if(r){
@@ -395,12 +400,10 @@
 		srvacquire(r->srv);
 		r->aux = nil;
 	}
-	if(f.io){
-		if(f.c)
-			sendp(f.c, nil);
-		sendp(iochan, f.io);
-	} else if(f.c)
-		chanfree(f.c);
+	if(io)
+		sendp(iochan, io);
+	if(c)
+		chanfree(c);
 	return i;
 }
 
@@ -823,12 +826,44 @@
 				respond(r, nil);
 				return;
 			}
+			while(nod->data == nil){
+				int offset, count, pos;
+
+				offset = r->ifcall.offset;
+				if(offset >= nod->d.length){
+					r->ofcall.count = 0;
+					respond(r, nil);
+					return;
+				}
+				/* are these people stupid? */
+				pos = (offset == 0) ? 1 : 2;
+				count = r->ifcall.count;
+				if((count + offset) > nod->d.length){
+					count = nod->d.length - offset;
+					pos = 3;
+				}
+				if(!ptprpc(r, GetPartialObject, 4|DataRecv, 
+					nod->handle, offset, count, pos, &p, &np)){
+					if(np <= count){
+						memmove(r->ofcall.data, p, np);
+						r->ofcall.count = np;
+						respond(r, nil);
+						free(p);
+						return;
+					}
+				}
+				free(p);
+			}
 			/* no break */
 		case Qthumb:
 			if(nod->data == nil){
+				p = nil;
+				np = 0;
 				if(ptprpc(r, TYPE(path)==Qthumb ? GetThumb : GetObject,
-					1|DataRecv, nod->handle, &p, &np) < 0)
+					1|DataRecv, nod->handle, &p, &np) < 0){
+					free(p);
 					break;
+				}
 				nod->data = p;
 				nod->ndata = np;
 			}
@@ -837,7 +872,6 @@
 			return;
 		}
 	}
-	free(p);
 	responderror(r);
 }
 
@@ -883,7 +917,7 @@
 	Channel *c;
 
 	if(c = r->oldreq->aux)
-		sendp(c, Einterrupt);
+		nbsendp(c, Einterrupt);
 	respond(r, nil);
 }
 
@@ -914,7 +948,7 @@
 }
 
 static int
-findendpoints(Dev *d, int *epin, int *epout)
+findendpoints(Dev *d, int *epin, int *epout, int *epint)
 {
 	int i;
 	Ep *ep;
@@ -921,10 +955,12 @@
 	Usbdev *ud;
 
 	ud = d->usb;
-	*epin = *epout = -1;
+	*epin = *epout = *epint = -1;
 	for(i=0; i<nelem(ud->ep); i++){
 		if((ep = ud->ep[i]) == nil)
 			continue;
+		if(ep->type == Eintr && *epint == -1)
+			*epint = ep->id;
 		if(ep->type != Ebulk)
 			continue;
 		if(ep->dir == Eboth || ep->dir == Ein)
@@ -933,9 +969,9 @@
 		if(ep->dir == Eboth || ep->dir == Eout)
 			if(*epout == -1)
 				*epout = ep->id;
-		if(*epin >= 0 && *epout >= 0)
-			return 0;
 	}
+	if(*epin >= 0 && *epout >= 0)
+		return 0;
 	return -1;
 }
 
@@ -963,7 +999,7 @@
 threadmain(int argc, char **argv)
 {
 	char name[64], desc[64];
-	int epin, epout;
+	int epin, epout, epint;
 	Dev *d;
 
 	ARGBEGIN {
@@ -981,10 +1017,12 @@
 		usage();
 	if((d = getdev(atoi(*argv))) == nil)
 		sysfatal("opendev: %r");
-	if(findendpoints(d, &epin, &epout)  < 0)
+	if(configdev(d) < 0)
+		sysfatal("configdev: %r");
+	if(findendpoints(d, &epin, &epout, &epint)  < 0)
 		sysfatal("findendpoints: %r");
 
-	usbep[In] = openep(d, epin);
+	usbep[In] = openep(usbep[Setup] = d, epin);
 	if(epin == epout){
 		incref(usbep[In]);
 		usbep[Out] = usbep[In];
@@ -996,7 +1034,6 @@
 	}
 	if(usbep[In]->dfd < 0 || usbep[Out]->dfd < 0)
 		sysfatal("open endpoints: %r");
-
 	iochan = chancreate(sizeof(Ioproc*), 1);
 	sendp(iochan, ioproc());