/* $Id: surfwax.c,v 1.7 2004/03/21 10:11:00 jmuelmen Exp $ */ #ifdef HAVE_SURFWAX #include #include #include #include #include #include #include #include "surfwax.h" /* * USB spec information * * This is all stuff grabbed from various USB specs and is pretty much * not subject to change */ /* * Device and/or Interface Class codes */ #define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ #define USB_CLASS_AUDIO 1 #define USB_CLASS_COMM 2 #define USB_CLASS_HID 3 #define USB_CLASS_PRINTER 7 #define USB_CLASS_MASS_STORAGE 8 #define USB_CLASS_HUB 9 #define USB_CLASS_DATA 10 #define USB_CLASS_VENDOR_SPEC 0xff /* * Descriptor types */ #define USB_DT_DEVICE 0x01 #define USB_DT_CONFIG 0x02 #define USB_DT_STRING 0x03 #define USB_DT_INTERFACE 0x04 #define USB_DT_ENDPOINT 0x05 #define USB_DT_HID 0x21 #define USB_DT_REPORT 0x22 #define USB_DT_PHYSICAL 0x23 #define USB_DT_HUB 0x29 /* * Descriptor sizes per descriptor type */ #define USB_DT_DEVICE_SIZE 18 #define USB_DT_CONFIG_SIZE 9 #define USB_DT_INTERFACE_SIZE 9 #define USB_DT_ENDPOINT_SIZE 7 #define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ #define USB_DT_HUB_NONVAR_SIZE 7 /* * Standard requests */ #define USB_REQ_GET_STATUS 0x00 #define USB_REQ_CLEAR_FEATURE 0x01 /* 0x02 is reserved */ #define USB_REQ_SET_FEATURE 0x03 /* 0x04 is reserved */ #define USB_REQ_SET_ADDRESS 0x05 #define USB_REQ_GET_DESCRIPTOR 0x06 #define USB_REQ_SET_DESCRIPTOR 0x07 #define USB_REQ_GET_CONFIGURATION 0x08 #define USB_REQ_SET_CONFIGURATION 0x09 #define USB_REQ_GET_INTERFACE 0x0A #define USB_REQ_SET_INTERFACE 0x0B #define USB_REQ_SYNCH_FRAME 0x0C #define USB_TYPE_STANDARD (0x00 << 5) #define USB_TYPE_CLASS (0x01 << 5) #define USB_TYPE_VENDOR (0x02 << 5) #define USB_TYPE_RESERVED (0x03 << 5) #define USB_RECIP_DEVICE 0x00 #define USB_RECIP_INTERFACE 0x01 #define USB_RECIP_ENDPOINT 0x02 #define USB_RECIP_OTHER 0x03 /* * Various libusb API related stuff */ #define USB_ENDPOINT_IN 0x80 #define USB_ENDPOINT_OUT 0x00 /* Error codes */ #define USB_ERROR_BEGIN 500000 /******************************************************************************/ /* Pontifex defines */ /******************************************************************************/ #define PFX_NEXT_BRD 0x00 #define PFX_READ 0x01 #define PFX_WRITE 0x02 #define PFX_OPEN 0x03 #define PFX_CLOSE 0x04 #define PFX_RESET 0x05 #define PFX_CTRL 0x06 #define PONTIFEX_READ_PORT 14159 #define PONTIFEX_WRITE_PORT 14160 #define BUFSIZE 1024 static int _sock; static struct sockaddr_in _sn, _rn; static int _sw (char *buf, int count) { int length; if ((length = sendto(_sock, buf, count, 0, &_sn, sizeof(_sn))) < 0) perror("sending datagram"); /* else printf("Sent %d bytes\n", length); */ return length; } static int _sr (char *buf, int count) { int length; if ((length = recv(_sock, buf, count, 0)) >= 0); /* printf("Read %d bytes: %s\n", length, buf); */ else perror("receiving datagram"); return length; } int usb_init () { int length; printf("Initializing surfwax.\n"); /* Create socket. */ _sock = socket(AF_INET, SOCK_DGRAM, 0); if (_sock < 0) { perror("opening datagram socket"); return 1; } /* bind the socket to the PONTIFEX_WRITE_PORT (since this is the socket that pontifex will send to) */ _rn.sin_family = AF_INET; _rn.sin_addr.s_addr = INADDR_ANY; _rn.sin_port = htons(PONTIFEX_WRITE_PORT); if (bind(_sock, (struct sockaddr *)&_rn, sizeof(_rn))) { perror("binding datagram socket"); return 1; } length = sizeof(_rn); if (getsockname(_sock, (struct sockaddr *)&_rn, &length)) { perror("getting socket name"); return 1; } printf("Socket has port %d... ", ntohs(_rn.sin_port)); if (ntohs(_rn.sin_port) != PONTIFEX_WRITE_PORT) { printf("we're unhappy.\n"); return 1; } else printf("we're happy.\n"); /* now make a sockaddr_in to send to */ _sn.sin_addr.s_addr = inet_addr("127.0.0.1"); printf("Sending to host 0x%x\n", ntohl(_sn.sin_addr.s_addr)); _sn.sin_family = AF_INET; _sn.sin_port = htons(PONTIFEX_READ_PORT); #if 0 /* Send message. */ if ((length = sendto(_sock, DATA, sizeof(DATA), 0, &_sn, sizeof(_sn))) < 0) perror("sending test datagram message"); /* else printf("Sent %d bytes\n", length); */ if ((length = recv(_sock, buf, BUFSIZE, 0)) >= 0) { buf[length] = 0; /* printf("Read %d bytes: %s\n", length, buf); */ } else perror("receiving datagram packet"); #endif printf("Succeeded.\n"); fflush(stdout); return 0; } int usb_bulk_write (int dev, int ep, char *buf, int count) { char wbuf[BUFSIZE]; int len; /* prefix: PFX_WRITE */ wbuf[0] = PFX_WRITE; wbuf[1] = dev & 0xff; wbuf[2] = ep & 0xff; /* the rest is buf */ if (count < BUFSIZE - 2) len = count; else len = BUFSIZE - 3; memcpy(wbuf + 3, buf, len); len += 3; return _sw(wbuf, len); } int usb_bulk_read (int dev, int ep, char *buf, int count) { char wbuf[BUFSIZE]; /* prefix: PFX_READ */ wbuf[0] = PFX_READ; wbuf[1] = dev & 0xff; wbuf[2] = ep & 0xff; wbuf[3] = count & 0xff; /* tell pontifex what we want */ _sw(wbuf, 4); /* reading from the socket will give us the result of reading from the board */ return _sr(buf, count); } int usb_control_msg (int dev, int rqt, int req, int val, int idx, char *buf, int count) /* will puke if you make the buffer big. Try to limity yourself to < 0xff - 10 (metadata). Sorry. */ { char wbuf[BUFSIZE]; int i = 0; /* prefix: PFX_CTRL */ wbuf[i++] = PFX_CTRL; wbuf[i++] = dev & 0xff; wbuf[i++] = rqt & 0xff; wbuf[i++] = req & 0xff; wbuf[i++] = (val >> 8) & 0xff; wbuf[i++] = val & 0xff; wbuf[i++] = (idx >> 8) & 0xff; wbuf[i++] = idx & 0xff; if (count + i + 1 < BUFSIZE) wbuf[i] = (count + i + 1) & 0xff; else wbuf[i] = BUFSIZE & 0xff; i++; if (count + i < BUFSIZE) memcpy(wbuf + i, buf, count); else memcpy(wbuf + i, buf, BUFSIZE - i); _sw(wbuf, count + i); return _sr(buf, count); } void usb_reset () { char buf = PFX_RESET; _sw(&buf, 1); } int usb_next_board () { char buf = PFX_NEXT_BRD; _sw(&buf, 1); _sr(&buf, 1); return buf; } int usb_open (int dev) { char buf[2]; buf[0] = PFX_OPEN; buf[1] = dev & 0xff; _sw(buf, 2); _sr(buf, 1); return buf[0]; } int usb_close (int dev) { char buf[2]; buf[0] = PFX_CLOSE; buf[1] = dev & 0xff; _sw(buf, 2); _sr(buf, 1); return buf[0]; } int usb_get_string (int dev, int string, char *name, int count) { return usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + string, 0x03, name, count); } #endif /* HAVE_SURFWAX */