/* Firmware for a Macintosh display adapter connected over USB Copyright (C) 2010 Jeroen Domburg This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ //Implement a simple USB interface thingy which can receive bulk packets. //No interrupts are used because of timing issues in the main code. #include "lpc134x.h" #include #define NOP() __asm volatile ("NOP") #define PACKED __attribute__((__packed__)) //Comment out to get debugging stuff on the monitor. #define printf(bla, ...) {} extern void gpioSet(int gpio, int val); typedef struct { unsigned char bmRequestType; unsigned char bRequest; unsigned short wValue; unsigned short wIndex; unsigned short wLength; } PACKED setupPacketTp; //Descriptor ref: //http://www.usbmadesimple.co.uk/ums_4.htm char myDevDescriptor[]={ 18, //length (18?) 1, //descriptor type 0x02,0x00, //usb ver 0xff, //class 0, //subclass 0, //protocol 64, //max packet size 0x34,0x12, //vendor id 0xAA,0x55, //product id 0x00,0x01, //device release 0x00, //manuf str index 0x00, //prod str index 0x00, //serial str index 0x01 //no of possible configs }; char myConfDescriptor[]={ //main config descriptor 9, //length of this descr 02, //type (config descr) 32,0, //total length 01, //no of interfaces 01, //select config no 1 to use this 00, //string descr of this config 0x80, //attributes 100, //max current drawn in 2ma steps //iface1 condfig descriptor 9, //len 4, //type (iface descr) 0, //iface number this descr describes 0, //alternate setting for this iface 2, //number of endpoints 0xff, //iface class 0, //Iface subclass 0, //Iface protocol 0, //String descr of this iface //Endpoint descriptor 7, //len 5, //type (endpoint descr) 0x3, //address. IN iface = +0x80 0x2, //attributes 32,0, //max packet size 10, //Interval to poll for data, in ms //Endpoint descriptor 7, //len 5, //type (endpoint descr) 0x83, //address. IN iface = +0x80 0x2, //attributes 32,0, //max packet size 10, //Interval to poll for data, in ms }; static int myAddr=0; static void dumpHex(unsigned char *buf, int len) { int x; if (len==0) return; for (x=0; x0) dumpHex((unsigned char* )data, len); } int readFromEp(int ep, unsigned int *data, int maxlen) { int x, dummy; USB_CTRL=((ep&0xF)<<2)|(1<<0); NOP(); NOP(); NOP(); int plen; do { plen=USB_RXPLEN; } while ((plen&0x400)==0); plen&=0x3ff; if (plen!=maxlen) printf("Ep %x: recv %i bufflen=%i!\n", ep, plen, maxlen); for (x=0; x<(plen); x+=4) { if (xmaxlen?maxlen:plen; } inline short swap16(unsigned short word) { return ((word&0xff)<<8)|(word>>8); } static inline void handleSetupPacket(setupPacketTp *p) { //A printf("Setup packet, type=%i, req=%i, val=%i, idx=%i\n", p->bmRequestType, p->bRequest, p->wValue, p->wIndex); // dumpHex((unsigned char* )p, 8); if (p->bmRequestType==0x80 && p->bRequest==6) { //Get descriptor. int index=swap16(p->wIndex); int len=p->wLength; if (swap16(p->wValue)==1) { //Dev descriptor. Write to ep. writeToEp(0, (unsigned int *)myDevDescriptor, myDevDescriptor[0]); printf("Dev desc written.\n"); } else if (swap16(p->wValue)==2) { int resplen=myConfDescriptor[2]+(myConfDescriptor[3]<<8); if (resplen>len) resplen=len; writeToEp(0, (unsigned int *)myConfDescriptor, len); printf("Conf desc written.\n"); } else { printf("EEK! Unhandled descriptor request!\n"); } } else if (p->bmRequestType==00 && p->bRequest==5) { //Set address //First send Ack with our old addresss 0 writeToEp(0, NULL, 0); //Then set new address. myAddr=(p->wValue&0x7F); wrCmd(0xD0); wrData(myAddr|0x80); wrCmd(0xD0); wrData(myAddr|0x80); printf("Set addr to %i.\n",myAddr); } else if (p->bmRequestType==00 && p->bRequest==9) { //Set configuration. //Just allow, there's only one of them anyway. writeToEp(0, NULL, 0); //Ok, other stuff can come in now. wrCmd(0xD8); wrData(1); printf("Enabled other endpoints!\n"); } else if (p->bmRequestType==0x40 && p->bRequest==1) { //vendor specific, gpio control, host->dev //Modify output wIndex to wValue gpioSet(p->wIndex, p->wValue); } else { printf("EEK! Unhandled setup packet!\n"); } } extern char usbData[64]; extern int usbDataLen; void usbHandle() { //Handle all the USB stuff by looking at any interrupts that would have been triggered. int ints=USB_DEVINTST; USB_DEVINTCLR=ints; // if ((ints&0x1fe)!=0) printf("Int status %x\n", ints); if (ints&(1<<7)) { int epstatus=rdCmd(0x46); printf("Ep3 int, status=%x\n", epstatus); usbDataLen=readFromEp(3, usbData, 64); return; } if (ints&(1<<8)) { int epstatus=rdCmd(0x47); printf("Ep3.1 int, status=%x\n", epstatus); } if (ints&(1<<1)) { //Endpoint0 int int epstatus=rdCmd(0x40); // printf("Ep0 int, status=%x\n", epstatus); if (epstatus&(1<<2)) { //Setup-packet. unsigned char setupPacket[8]; readFromEp(0, (unsigned int *)setupPacket, 8); handleSetupPacket((setupPacketTp*) setupPacket); } } if (ints&(1<<9)) { //Device status change int status=rdCmd(0xfe); // printf("Dev status is now %x\n",status); if (!(status&1)) { //Reconnect, damn you! /* wrCmd(0xFE); wrData(0x1); myAddr=0; */ } } }