#lang scheme/base
(require scheme/foreign)

;; from /usr/include/usb.h

;; /*
;;  * Prototypes, structure definitions and macros.
;;  *
;;  * Copyright (c) 2000-2003 Johannes Erdfelt <johannes@erdfelt.com>
;;  *
;;  * This library is covered by the LGPL, read LICENSE for details.
;;  *
;;  * This file (and only this file) may alternatively be licensed under the
;;  * BSD license as well, read LICENSE for details.
;;  */

;; 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_PTP			6)
(define USB_CLASS_HUB			9)
(define USB_CLASS_DATA			10)
(define USB_CLASS_VENDOR_SPEC		#xff)

;; Descriptor types

(define USB_DT_DEVICE			#x01)
(define USB_DT_CONFIG			#x02)
(define USB_DT_STRING			#x03)
(define USB_DT_INTERFACE		#x04)
(define USB_DT_ENDPOINT			#x05)

(define USB_DT_HID			#x21)
(define USB_DT_REPORT			#x22)
(define USB_DT_PHYSICAL			#x23)
(define USB_DT_HUB			#x29)

;; Descriptor sizes per descriptor type

(define USB_DT_DEVICE_SIZE		18)
(define USB_DT_CONFIG_SIZE		9)
(define USB_DT_ENDPOINT_AUDIO_SIZE	9)	;; Audio extension

;; from "cpp /usr/include/usb.h"

;; All structs are 'packed'.

(define-cstruct _usb_descriptor_header 
  ([bLength _int8]
   [bDescriptorType _int8]))

(define-cstruct _usb_string_descriptor 
  ([bLength _int8]
   [bDescriptorType _int8]
   [wData _int16]))

(define-cstruct _usb_hid_descriptor
  ([bLength _int8]
   [bDescriptorType _int8]
   [bcdHID _int16]
   [bCountryCode _int8]
   [bNumDescriptors _int8]))

(define-cstruct _usb_endpoint_descriptor
  ([bLength _int8]
   [bDescriptorType _int8]
   [bEndpointAddress _int8]
   [bmAttributes _int8]
   [wMaxPacketSize _int16]
   [bInterval _int8]
   [bRefresh _int8]
   [bSynchAddress _int8]
  ;;unsigned char *extra;
  ;;int extralen;

(define-cstruct _usb_interface_descriptor
  ([bLength _int8]
   [bDescriptorType _int8]
   [bInterfaceNumber _int8]
   [bAlternateSetting _int8]
   [bNumEndpoints _int8]
   [bInterfaceClass _int8]
   [bInterfaceSubClass _int8]
   [bInterfaceProtocol _int8]
   [iInterface _int8]
   ;; struct usb_endpoint_descriptor *endpoint;

   ;; unsigned char *extra;
   ;; int extralen;

(define-cstruct _usb_interface
  ([alsetting _usb_interface_descriptor-pointer]
   [num_altsetting _int]))

(define-cstruct _usb_config_descriptor
  ([bLength _int8]
   [bDescriptorType _int8]
   [wTotalLength _int16]
   [bNumInterfaces _int8]
   [bConfigurationValue _int8]
   [iConfiguration _int8]
   [bmAttributes _int8]
   [MaxPower _int8]
   [interface _usb_interface-pointer]
   ;; unsigned char *extra;
   ;; int extralen;

(define-cstruct _usb_device_descriptor
  ([bLength _int8]
   [bDescriptorType _int8]
   [bcdUSB _int16]
   [bDeviceClass _int8]
   [bDeviceSubClass _int8]
   [bDeviceProtocol _int8]
   [bMaxPacketSize0 _int8]
   [idVendor _int16]
   [idProduct _int16]
   [bcdDevice _int16]
   [iManufacturer _int8]
   [iProduct _int8]
   [iSerialNumber _int8]
   [bNumConfigurations _int8]))

(define-cstruct _usb_ctrl_setup
  ([bRequestType _int8]
   [bRequest _int8]
   [wValue _int16]
   [wIndex _int16]
   [wLength _int16]))

(define <<< arithmetic-shift)

;; Standard requests

(define USB_REQ_GET_STATUS		#x00)
(define USB_REQ_CLEAR_FEATURE		#x01)
;; #x02 is reserved
(define USB_REQ_SET_FEATURE		#x03)
;; #x04 is reserved
(define USB_REQ_SET_ADDRESS		#x05)
(define USB_REQ_SYNCH_FRAME		#x0C)

(define USB_TYPE_STANDARD		(<<< #x00 5))
(define USB_TYPE_CLASS			(<<< #x01 5))
(define USB_TYPE_VENDOR			(<<< #x02 5))
(define USB_TYPE_RESERVED		(<<< #x03 5))

(define USB_RECIP_DEVICE		#x00)
(define USB_RECIP_INTERFACE		#x01)
(define USB_RECIP_ENDPOINT		#x02)
(define USB_RECIP_OTHER			#x03)

;; Various libusb API related stuff

(define USB_ENDPOINT_IN			#x80)
(define USB_ENDPOINT_OUT		#x00)

;; Error codes
(define USB_ERROR_BEGIN			500000)

(define-cstruct _usb_device
  ([next _usb_device-pointer]
   [prev _usb_device-pointer]
;;   char filename[4096 + 1];
   [bus  _usb_bus-pointer]
   [descriptor _usb_device_descriptor]
   [config     _usb_config_descriptor-pointer]
   [dev        _void]  ;; *void
   [devnum     _int8]
   [num_children _int8]
   [children   _usb_devicep-pointer]))

;; FIXME: double pointers?
(define-cstruct _usb_devicep
  ([devicep _usb_device-pointer]))

(define-cstruct _usb_bus
  ([next _usb_bus-pointer]
   [prev _usb_bus-pointer]
;;   char dirname[4096 + 1];
   [device _usb_device-pointer]
   [location _int32]
   [root_dev _usb_device-pointer]))

;; struct usb_dev_handle;
;; typedef struct usb_dev_handle usb_dev_handle;

;; extern struct usb_bus *usb_busses;
;; # 284 "/usr/include/usb.h"
;; usb_dev_handle *usb_open(struct usb_device *dev);
;; int usb_close(usb_dev_handle *dev);
;; int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf,
;;  size_t buflen);
;; int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf,
;;  size_t buflen);

;; int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep,
;;  unsigned char type, unsigned char index, void *buf, int size);
;; int usb_get_descriptor(usb_dev_handle *udev, unsigned char type,
;;  unsigned char index, void *buf, int size);

;; int usb_bulk_write(usb_dev_handle *dev, int ep, const char *bytes, int size,
;;  int timeout);
;; int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size,
;;  int timeout);
;; int usb_interrupt_write(usb_dev_handle *dev, int ep, const char *bytes, int size,
;;         int timeout);
;; int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
;;         int timeout);
;; int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
;;  int value, int index, char *bytes, int size, int timeout);
;; int usb_set_configuration(usb_dev_handle *dev, int configuration);
;; int usb_claim_interface(usb_dev_handle *dev, int interface);
;; int usb_release_interface(usb_dev_handle *dev, int interface);
;; int usb_set_altinterface(usb_dev_handle *dev, int alternate);
;; int usb_resetep(usb_dev_handle *dev, unsigned int ep);
;; int usb_clear_halt(usb_dev_handle *dev, unsigned int ep);
;; int usb_reset(usb_dev_handle *dev);

;; int usb_get_driver_np(usb_dev_handle *dev, int interface, char *name,
;;  unsigned int namelen);

;; int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface);

;; char *usb_strerror(void);

;; void usb_init(void);
;; void usb_set_debug(int level);
;; int usb_find_busses(void);
;; int usb_find_devices(void);
;; struct usb_device *usb_device(usb_dev_handle *dev);
;; struct usb_bus *usb_get_busses(void);