Add kernel module sources
This commit is contained in:
parent
a159e2a668
commit
763a5c7436
2
brick/kernel/Makefile
Normal file
2
brick/kernel/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
obj-m += $(MOD).o
|
||||
|
1382
brick/kernel/computil.c
Normal file
1382
brick/kernel/computil.c
Normal file
File diff suppressed because it is too large
Load Diff
755
brick/kernel/d_usbdev.c
Normal file
755
brick/kernel/d_usbdev.c
Normal file
@ -0,0 +1,755 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This UsbDev file is based on and inheritated from
|
||||
* the original file (zero.c) and work done by David Brownell
|
||||
*
|
||||
* >> zero.c -- Gadget Zero, for USB development <<
|
||||
*
|
||||
* >> Copyright (C) 2003-2008 David Brownell <<
|
||||
* >> Copyright (C) 2008 by Nokia Corporation <<
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \page UsbdevModule USB device Module
|
||||
*
|
||||
*
|
||||
*- \subpage UsbdevModuleResources
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PCASM
|
||||
#include <asm/types.h>
|
||||
#endif
|
||||
|
||||
#include "source/lms2012.h"
|
||||
#include "source/am1808.h"
|
||||
|
||||
|
||||
#define MODULE_NAME "usbdev_module"
|
||||
#define DEVICE1_NAME USBDEV_DEVICE
|
||||
|
||||
|
||||
|
||||
static int ModuleInit(void);
|
||||
static void ModuleExit(void);
|
||||
|
||||
#define __USE_POSIX
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
|
||||
#ifndef PCASM
|
||||
#include <linux/hrtimer.h>
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/hrtimer.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include <linux/ioport.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
void myReset(void);
|
||||
static int dUsbInit(void);
|
||||
static void dUsbExit(void);
|
||||
static struct fsg_common *fsg_common;
|
||||
|
||||
#include "computil.c" // The composite framework used as utility file
|
||||
#include <../drivers/usb/gadget/gadget_chips.h>
|
||||
#include <../drivers/usb/gadget/usbstring.c>
|
||||
#include <../drivers/usb/gadget/config.c>
|
||||
#include <../drivers/usb/gadget/epautoconf.c>
|
||||
|
||||
#include "f_mass_storage.c"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Kbuild is not very cooperative with respect to linking separately
|
||||
* compiled library objects into one module. So for now we won't use
|
||||
* separate compilation ... ensuring init/exit sections work to shrink
|
||||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
|
||||
#include <../drivers/usb/gadget/g_zero.h>
|
||||
#define MAX_EP_SIZE 1024
|
||||
#define MAX_FULLSPEED_EP_SIZE 64
|
||||
unsigned buflen = MAX_EP_SIZE ;
|
||||
char usb_char_buffer_in[MAX_EP_SIZE];
|
||||
char usb_full_buffer_in[MAX_FULLSPEED_EP_SIZE];
|
||||
int usb_char_in_length = 0;
|
||||
char usb_char_buffer_out[MAX_EP_SIZE];
|
||||
char usb_full_buffer_out[MAX_FULLSPEED_EP_SIZE];
|
||||
int usb_char_out_length = 0;
|
||||
|
||||
#define SHM_LENGTH (sizeof(UsbSpeedDefault))
|
||||
#define NPAGES ((SHM_LENGTH + PAGE_SIZE - 1) / PAGE_SIZE)
|
||||
static void *kmalloc_ptr;
|
||||
|
||||
#include "usb_function.c" // Specific USB functionality
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("The LEGO Group");
|
||||
MODULE_DESCRIPTION(MODULE_NAME);
|
||||
MODULE_SUPPORTED_DEVICE(DEVICE1_NAME);
|
||||
|
||||
module_init(ModuleInit);
|
||||
module_exit(ModuleExit);
|
||||
|
||||
#else
|
||||
// Keep Eclipse happy
|
||||
#endif
|
||||
|
||||
// USB main stuff
|
||||
|
||||
#define DRIVER_VERSION "31jan2011->"
|
||||
|
||||
#ifndef PCASM
|
||||
module_param(buflen, uint, 0);
|
||||
#else
|
||||
// Keep Eclipse happy
|
||||
#endif
|
||||
|
||||
static int loopdefault = 0;
|
||||
#ifndef PCASM
|
||||
module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
|
||||
#else
|
||||
// Keep Eclipse happy
|
||||
#endif
|
||||
|
||||
#define DRIVER_VENDOR_NUM 0x0694 // LEGO Group
|
||||
#define DRIVER_PRODUCT_NUM 0x0005 // No. 5 in a row
|
||||
#define DEFAULT_AUTORESUME 0
|
||||
|
||||
/* If the optional "autoresume" mode is enabled, it provides good
|
||||
* functional coverage for the "USBCV" test harness from USB-IF.
|
||||
* It's always set if OTG mode is enabled.
|
||||
*/
|
||||
|
||||
unsigned autoresume = DEFAULT_AUTORESUME;
|
||||
module_param(autoresume, uint, S_IRUGO);
|
||||
|
||||
#ifndef PCASM
|
||||
MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
|
||||
#else
|
||||
// Keep Eclipse happy
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static struct usb_device_descriptor device_desc = {
|
||||
.bLength = sizeof device_desc,
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
|
||||
.bcdUSB = cpu_to_le16(0x0200),
|
||||
.bDeviceClass = 0xEF,
|
||||
.bDeviceSubClass = 2,
|
||||
.bDeviceProtocol = 1,
|
||||
|
||||
/*.bMaxPacketSize0 = f(hardware) */
|
||||
.idVendor = cpu_to_le16(DRIVER_VENDOR_NUM),
|
||||
.idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM),
|
||||
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USB_OTG
|
||||
struct usb_otg_descriptor otg_descriptor = {
|
||||
.bLength = sizeof otg_descriptor,
|
||||
.bDescriptorType = USB_DT_OTG,
|
||||
|
||||
/* REVISIT SRP-only hardware is possible, although
|
||||
* it would not be called "OTG" ...
|
||||
*/
|
||||
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
|
||||
};
|
||||
|
||||
const struct usb_descriptor_header *otg_desc[] = {
|
||||
(struct usb_descriptor_header *) &otg_descriptor,
|
||||
NULL,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* string IDs are assigned dynamically */
|
||||
|
||||
#define STRING_MANUFACTURER_IDX 0
|
||||
#define STRING_PRODUCT_IDX 1
|
||||
#define STRING_SERIAL_IDX 2
|
||||
|
||||
static char manufacturer[] = "LEGO Group";
|
||||
static char serial[] = "123456789ABC ";
|
||||
static char longname[] = "EV3 brick ";
|
||||
|
||||
static struct usb_string strings_dev[3] = {
|
||||
[STRING_MANUFACTURER_IDX].s = manufacturer,
|
||||
[STRING_PRODUCT_IDX].s = longname,
|
||||
[STRING_SERIAL_IDX].s = serial
|
||||
};
|
||||
|
||||
|
||||
static struct usb_gadget_strings stringtab_dev = {
|
||||
.language = 0x0409, /* en-us */
|
||||
.strings = strings_dev,
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings *dev_strings[] = {
|
||||
&stringtab_dev,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
struct usb_request *alloc_ep_req(struct usb_ep *ep)
|
||||
{
|
||||
struct usb_request *req;
|
||||
|
||||
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
|
||||
if (req) {
|
||||
req->length = buflen;
|
||||
req->buf = kmalloc(buflen, GFP_ATOMIC);
|
||||
if (!req->buf) {
|
||||
usb_ep_free_request(ep, req);
|
||||
req = NULL;
|
||||
}
|
||||
}
|
||||
return req;
|
||||
}
|
||||
|
||||
void free_ep_req(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
kfree(req->buf);
|
||||
usb_ep_free_request(ep, req);
|
||||
}
|
||||
|
||||
static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
|
||||
{
|
||||
int value;
|
||||
|
||||
if (ep->driver_data) {
|
||||
value = usb_ep_disable(ep);
|
||||
if (value < 0)
|
||||
DBG(cdev, "disable %s --> %d\n",
|
||||
ep->name, value);
|
||||
ep->driver_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void disable_endpoints(struct usb_composite_dev *cdev,
|
||||
struct usb_ep *in, struct usb_ep *out)
|
||||
{
|
||||
disable_ep(cdev, in);
|
||||
disable_ep(cdev, out);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static struct timer_list autoresume_timer;
|
||||
|
||||
static void zero_autoresume(unsigned long _c)
|
||||
{
|
||||
struct usb_composite_dev *cdev = (void *)_c;
|
||||
struct usb_gadget *g = cdev->gadget;
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("zero_autoresume\n\r");
|
||||
#endif
|
||||
|
||||
/* unconfigured devices can't issue wakeups */
|
||||
if (!cdev->config)
|
||||
return;
|
||||
|
||||
/* Normally the host would be woken up for something
|
||||
* more significant than just a timer firing; likely
|
||||
* because of some direct user request.
|
||||
*/
|
||||
if (g->speed != USB_SPEED_UNKNOWN) {
|
||||
int status = usb_gadget_wakeup(g);
|
||||
INFO(cdev, "%s --> %d\n", __func__, status);
|
||||
}
|
||||
}
|
||||
|
||||
static void zero_suspend(struct usb_composite_dev *cdev)
|
||||
{
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("zero_suspend\n\r");
|
||||
#endif
|
||||
|
||||
if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
|
||||
return;
|
||||
|
||||
if (autoresume) {
|
||||
mod_timer(&autoresume_timer, jiffies + (HZ * autoresume));
|
||||
DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume);
|
||||
} else
|
||||
DBG(cdev, "%s\n", __func__);
|
||||
}
|
||||
|
||||
static void zero_resume(struct usb_composite_dev *cdev)
|
||||
{
|
||||
DBG(cdev, "%s\n", __func__);
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("zero_resume\n\r");
|
||||
#endif
|
||||
|
||||
del_timer(&autoresume_timer);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int msg_bind(struct usb_composite_dev *cdev);
|
||||
static void msg_bind2(struct usb_composite_dev *cdev);
|
||||
|
||||
static int zero_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
int gcnum;
|
||||
struct usb_gadget *gadget = cdev->gadget;
|
||||
int id;
|
||||
|
||||
/* Allocate string descriptor numbers ... note that string
|
||||
* contents can be overridden by the composite_dev glue.
|
||||
*/
|
||||
id = usb_string_id(cdev);
|
||||
if (id < 0)
|
||||
return id;
|
||||
|
||||
strings_dev[STRING_MANUFACTURER_IDX].id = id;
|
||||
device_desc.iManufacturer = id;
|
||||
|
||||
id = usb_string_id(cdev);
|
||||
if (id < 0)
|
||||
return id;
|
||||
|
||||
|
||||
strings_dev[STRING_PRODUCT_IDX].id = id;
|
||||
device_desc.iProduct = id;
|
||||
|
||||
id = usb_string_id(cdev);
|
||||
if (id < 0)
|
||||
return id;
|
||||
|
||||
|
||||
strings_dev[STRING_SERIAL_IDX].id = id;
|
||||
device_desc.iSerialNumber = id;
|
||||
|
||||
id = msg_bind(cdev);
|
||||
if (id < 0)
|
||||
return id;
|
||||
|
||||
setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);
|
||||
|
||||
rudolf_add(cdev, autoresume != 0);
|
||||
|
||||
gcnum = usb_gadget_controller_number(gadget);
|
||||
if (gcnum >= 0)
|
||||
device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
|
||||
else {
|
||||
/* gadget zero is so simple (for now, no altsettings) that
|
||||
* it SHOULD NOT have problems with bulk-capable hardware.
|
||||
* so just warn about unrcognized controllers -- don't panic.
|
||||
*
|
||||
* things like configuration and altsetting numbering
|
||||
* can need hardware-specific attention though.
|
||||
*/
|
||||
pr_warning("%s: controller '%s' not recognized\n",
|
||||
longname, gadget->name);
|
||||
device_desc.bcdDevice = cpu_to_le16(0x9999);
|
||||
}
|
||||
|
||||
msg_bind2(cdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zero_unbind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("zero_unbind\n\r");
|
||||
#endif
|
||||
|
||||
del_timer_sync(&autoresume_timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_composite_driver zero_driver = {
|
||||
.name = "zero",
|
||||
.dev = &device_desc,
|
||||
.strings = dev_strings,
|
||||
.bind = zero_bind,
|
||||
.unbind = zero_unbind,
|
||||
.suspend = zero_suspend,
|
||||
.resume = zero_resume,
|
||||
};
|
||||
|
||||
static int dUsbInit(void)
|
||||
{
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("dUsbInit\n\r");
|
||||
#endif
|
||||
|
||||
UsbSpeed.Speed = FULL_SPEED; // default to FULL_SPEED if not connected to a HIGH-SPEED
|
||||
(*pUsbSpeed).Speed = FULL_SPEED; // HOST. If not connected to HIGH-SPEED we assume we're
|
||||
// wanting (or at least doing) Daisy Chain
|
||||
return usb_composite_register(&zero_driver);
|
||||
}
|
||||
|
||||
static void dUsbExit(void)
|
||||
{
|
||||
usb_composite_unregister(&zero_driver);
|
||||
}
|
||||
|
||||
// DEVICE1 char device stuff ********************************************************************
|
||||
|
||||
static ssize_t Device1Write(struct file *File,const char *Buffer,size_t Count,loff_t *Data)
|
||||
{
|
||||
// Write data for the HOST to poll - Stuff sent to the HOST
|
||||
|
||||
int BytesWritten = 0;
|
||||
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("Device1Write - usb_char_in_length = %d\n", usb_char_in_length);
|
||||
#endif
|
||||
|
||||
if (usb_char_in_length == 0) // ready for more
|
||||
{ // else wait in USER layer
|
||||
BytesWritten = Count;
|
||||
copy_from_user(usb_char_buffer_in, Buffer, BytesWritten);
|
||||
usb_char_in_length = BytesWritten;
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("WR = %d, %d -- ", usb_char_buffer_in[2], usb_char_buffer_in[3]);
|
||||
#endif
|
||||
|
||||
if(USB_DATA_PENDING == input_state)
|
||||
{
|
||||
// Already we've a failed tx (HOST part starwing??
|
||||
|
||||
input_state = USB_DATA_READY;
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("DATA_PENDING SECOND time and reset!! in Device1Write\n\r");
|
||||
#endif
|
||||
}
|
||||
|
||||
if(USB_DATA_READY == input_state)
|
||||
{
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("USB_DATA_READY in Device1Write\n\r");
|
||||
#endif
|
||||
|
||||
input_state = USB_DATA_BUSY;
|
||||
write_data_to_the_host(save_in_ep, save_in_req);
|
||||
usb_req_arm(save_in_ep, save_in_req); // new request
|
||||
}
|
||||
else
|
||||
{
|
||||
input_state = USB_DATA_PENDING;
|
||||
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("DATA_PENDING in Device1Write\n\r");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("usbdev %d written\n\r", BytesWritten);
|
||||
#endif
|
||||
|
||||
return (BytesWritten); // Zero means USB was not ready yet
|
||||
}
|
||||
|
||||
static ssize_t Device1Read(struct file *File,char *Buffer,size_t Count,loff_t *Offset)
|
||||
{
|
||||
// Read the bits'n'bytes from the HOST
|
||||
int BytesRead = 0;
|
||||
|
||||
if (usb_char_out_length > 0) // Something to look at
|
||||
{
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("Some bytes to READ?\n\r");
|
||||
#endif
|
||||
|
||||
copy_to_user(Buffer, usb_char_buffer_out, Count);
|
||||
BytesRead = usb_char_out_length;
|
||||
usb_char_out_length = 0;
|
||||
}
|
||||
return (BytesRead);
|
||||
}
|
||||
|
||||
static int Device1Mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = remap_pfn_range(vma,vma->vm_start,virt_to_phys((void*)((unsigned long)pUsbSpeed)) >> PAGE_SHIFT,vma->vm_end-vma->vm_start,PAGE_SHARED);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
ret = -EAGAIN;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
static const struct file_operations Device1Entries =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.read = Device1Read,
|
||||
.write = Device1Write,
|
||||
.mmap = Device1Mmap
|
||||
};
|
||||
|
||||
|
||||
static struct miscdevice Device1 =
|
||||
{
|
||||
MISC_DYNAMIC_MINOR,
|
||||
DEVICE1_NAME,
|
||||
&Device1Entries
|
||||
};
|
||||
|
||||
|
||||
static int Device1Init(void)
|
||||
{
|
||||
int Result = -1;
|
||||
UWORD *pTemp;
|
||||
int i;
|
||||
|
||||
Result = misc_register(&Device1);
|
||||
if (Result)
|
||||
{
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk(" %s device register failed\n",DEVICE1_NAME);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk(" %s device register OK\n",DEVICE1_NAME);
|
||||
#endif
|
||||
|
||||
// allocate kernel shared memory for DaisyChain Speed info
|
||||
|
||||
if ((kmalloc_ptr = kmalloc((NPAGES + 2) * PAGE_SIZE, GFP_KERNEL)) != NULL)
|
||||
{
|
||||
|
||||
pTemp = (UWORD*)((((unsigned long)kmalloc_ptr) + PAGE_SIZE - 1) & PAGE_MASK);
|
||||
|
||||
for (i = 0; i < NPAGES * PAGE_SIZE; i += PAGE_SIZE)
|
||||
{
|
||||
SetPageReserved(virt_to_page(((unsigned long)pTemp) + i));
|
||||
}
|
||||
|
||||
pUsbSpeed = (USB_SPEED*)pTemp;
|
||||
}
|
||||
|
||||
dUsbInit();
|
||||
}
|
||||
|
||||
return (Result);
|
||||
}
|
||||
|
||||
static void Device1Exit(void)
|
||||
{
|
||||
int i;
|
||||
UWORD *pTemp = (UWORD*)pUsbSpeed;
|
||||
|
||||
dUsbExit();
|
||||
|
||||
pUsbSpeed = &UsbSpeedDefault;
|
||||
|
||||
for (i = 0; i < NPAGES * PAGE_SIZE; i+= PAGE_SIZE)
|
||||
{
|
||||
ClearPageReserved(virt_to_page(((unsigned long)pTemp) + i));
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk(" %s memory page %d unmapped\n",DEVICE1_NAME,i);
|
||||
#endif
|
||||
}
|
||||
|
||||
kfree(kmalloc_ptr);
|
||||
|
||||
misc_deregister(&Device1);
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk(" %s device unregistered\n",DEVICE1_NAME);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// MODULE *********************************************************************
|
||||
|
||||
char *HostStr; // Used for HostName - or NOT used at all
|
||||
char *SerialStr; // Used for Serial number (I.e. BT number)
|
||||
|
||||
module_param (HostStr, charp, 0);
|
||||
module_param (SerialStr, charp, 0);
|
||||
|
||||
static int ModuleInit(void)
|
||||
{
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("%s Module init started\r\n",MODULE_NAME);
|
||||
#endif
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("This is DEFAULT NAME: %s\n\r", longname);
|
||||
#endif
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("\n\rThis is the HostStr: %s\n\r", HostStr);
|
||||
#endif
|
||||
|
||||
strcpy(longname, HostStr);
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("\n\rThis is the INSMODed NAME: %s\n\r", longname);
|
||||
#endif
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("\n\rThis is the DEFAULT SerialNumber: %s\n\r", serial);
|
||||
#endif
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("\n\rThis is the SerialStr: %s\n\r", SerialStr);
|
||||
#endif
|
||||
|
||||
strcpy(serial, SerialStr);
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("\n\rThis is the INSMODed SerialNumber (BT mac): %s\n\r", serial);
|
||||
#endif
|
||||
|
||||
Device1Init();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void ModuleExit(void)
|
||||
{
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("%s exit started\n",MODULE_NAME);
|
||||
#endif
|
||||
|
||||
Device1Exit();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// MSG
|
||||
|
||||
|
||||
/****************************** Configurations ******************************/
|
||||
|
||||
static struct fsg_module_parameters fsg_mod_data = {
|
||||
.stall = 1
|
||||
};
|
||||
FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
|
||||
|
||||
/****************************** Gadget Bind ******************************/
|
||||
|
||||
|
||||
static void msg_bind2(struct usb_composite_dev *cdev)
|
||||
{
|
||||
fsg_common_put(fsg_common);
|
||||
}
|
||||
|
||||
static int msg_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
/* set up mass storage function */
|
||||
fsg_common = fsg_common_from_params(0, cdev, &fsg_mod_data);
|
||||
if (IS_ERR(fsg_common)) {
|
||||
return PTR_ERR(fsg_common);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int msg_config(struct usb_configuration *c) {
|
||||
return fsg_add(c->cdev, c, fsg_common);
|
||||
}
|
||||
|
||||
void myReset() {
|
||||
dUsbExit();
|
||||
dUsbInit();
|
||||
}
|
3147
brick/kernel/f_mass_storage.c
Normal file
3147
brick/kernel/f_mass_storage.c
Normal file
File diff suppressed because it is too large
Load Diff
276
brick/kernel/gadget_chips.h
Normal file
276
brick/kernel/gadget_chips.h
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* USB device controllers have lots of quirks. Use these macros in
|
||||
* gadget drivers or other code that needs to deal with them, and which
|
||||
* autoconfigures instead of using early binding to the hardware.
|
||||
*
|
||||
* This SHOULD eventually work like the ARM mach_is_*() stuff, driven by
|
||||
* some config file that gets updated as new hardware is supported.
|
||||
* (And avoiding all runtime comparisons in typical one-choice configs!)
|
||||
*
|
||||
* NOTE: some of these controller drivers may not be available yet.
|
||||
* Some are available on 2.4 kernels; several are available, but not
|
||||
* yet pushed in the 2.6 mainline tree.
|
||||
*/
|
||||
|
||||
#ifndef __GADGET_CHIPS_H
|
||||
#define __GADGET_CHIPS_H
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_NET2280
|
||||
#define gadget_is_net2280(g) !strcmp("net2280", (g)->name)
|
||||
#else
|
||||
#define gadget_is_net2280(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_AMD5536UDC
|
||||
#define gadget_is_amd5536udc(g) !strcmp("amd5536udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_amd5536udc(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_DUMMY_HCD
|
||||
#define gadget_is_dummy(g) !strcmp("dummy_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_dummy(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_PXA25X
|
||||
#define gadget_is_pxa(g) !strcmp("pxa25x_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_pxa(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_GOKU
|
||||
#define gadget_is_goku(g) !strcmp("goku_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_goku(g) 0
|
||||
#endif
|
||||
|
||||
/* SH3 UDC -- not yet ported 2.4 --> 2.6 */
|
||||
#ifdef CONFIG_USB_GADGET_SUPERH
|
||||
#define gadget_is_sh(g) !strcmp("sh_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_sh(g) 0
|
||||
#endif
|
||||
|
||||
/* not yet stable on 2.6 (would help "original Zaurus") */
|
||||
#ifdef CONFIG_USB_GADGET_SA1100
|
||||
#define gadget_is_sa1100(g) !strcmp("sa1100_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_sa1100(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_LH7A40X
|
||||
#define gadget_is_lh7a40x(g) !strcmp("lh7a40x_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_lh7a40x(g) 0
|
||||
#endif
|
||||
|
||||
/* handhelds.org tree (?) */
|
||||
#ifdef CONFIG_USB_GADGET_MQ11XX
|
||||
#define gadget_is_mq11xx(g) !strcmp("mq11xx_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_mq11xx(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_OMAP
|
||||
#define gadget_is_omap(g) !strcmp("omap_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_omap(g) 0
|
||||
#endif
|
||||
|
||||
/* not yet ported 2.4 --> 2.6 */
|
||||
#ifdef CONFIG_USB_GADGET_N9604
|
||||
#define gadget_is_n9604(g) !strcmp("n9604_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_n9604(g) 0
|
||||
#endif
|
||||
|
||||
/* various unstable versions available */
|
||||
#ifdef CONFIG_USB_GADGET_PXA27X
|
||||
#define gadget_is_pxa27x(g) !strcmp("pxa27x_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_pxa27x(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_ATMEL_USBA
|
||||
#define gadget_is_atmel_usba(g) !strcmp("atmel_usba_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_atmel_usba(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_S3C2410
|
||||
#define gadget_is_s3c2410(g) !strcmp("s3c2410_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_s3c2410(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_AT91
|
||||
#define gadget_is_at91(g) !strcmp("at91_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_at91(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_IMX
|
||||
#define gadget_is_imx(g) !strcmp("imx_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_imx(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_FSL_USB2
|
||||
#define gadget_is_fsl_usb2(g) !strcmp("fsl-usb2-udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_fsl_usb2(g) 0
|
||||
#endif
|
||||
|
||||
/* Mentor high speed function controller */
|
||||
/* from Montavista kernel (?) */
|
||||
#ifdef CONFIG_USB_GADGET_MUSBHSFC
|
||||
#define gadget_is_musbhsfc(g) !strcmp("musbhsfc_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_musbhsfc(g) 0
|
||||
#endif
|
||||
|
||||
/* Mentor high speed "dual role" controller, in peripheral role */
|
||||
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
|
||||
#define gadget_is_musbhdrc(g) !strcmp("musb_hdrc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_musbhdrc(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_LANGWELL
|
||||
#define gadget_is_langwell(g) (!strcmp("langwell_udc", (g)->name))
|
||||
#else
|
||||
#define gadget_is_langwell(g) 0
|
||||
#endif
|
||||
|
||||
/* from Montavista kernel (?) */
|
||||
#ifdef CONFIG_USB_GADGET_MPC8272
|
||||
#define gadget_is_mpc8272(g) !strcmp("mpc8272_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_mpc8272(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_M66592
|
||||
#define gadget_is_m66592(g) !strcmp("m66592_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_m66592(g) 0
|
||||
#endif
|
||||
|
||||
/* Freescale CPM/QE UDC SUPPORT */
|
||||
#ifdef CONFIG_USB_GADGET_FSL_QE
|
||||
#define gadget_is_fsl_qe(g) !strcmp("fsl_qe_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_fsl_qe(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_CI13XXX
|
||||
#define gadget_is_ci13xxx(g) (!strcmp("ci13xxx_udc", (g)->name))
|
||||
#else
|
||||
#define gadget_is_ci13xxx(g) 0
|
||||
#endif
|
||||
|
||||
// CONFIG_USB_GADGET_SX2
|
||||
// CONFIG_USB_GADGET_AU1X00
|
||||
// ...
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_R8A66597
|
||||
#define gadget_is_r8a66597(g) !strcmp("r8a66597_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_r8a66597(g) 0
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* usb_gadget_controller_number - support bcdDevice id convention
|
||||
* @gadget: the controller being driven
|
||||
*
|
||||
* Return a 2-digit BCD value associated with the peripheral controller,
|
||||
* suitable for use as part of a bcdDevice value, or a negative error code.
|
||||
*
|
||||
* NOTE: this convention is purely optional, and has no meaning in terms of
|
||||
* any USB specification. If you want to use a different convention in your
|
||||
* gadget driver firmware -- maybe a more formal revision ID -- feel free.
|
||||
*
|
||||
* Hosts see these bcdDevice numbers, and are allowed (but not encouraged!)
|
||||
* to change their behavior accordingly. For example it might help avoiding
|
||||
* some chip bug.
|
||||
*/
|
||||
static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
|
||||
{
|
||||
if (gadget_is_net2280(gadget))
|
||||
return 0x01;
|
||||
else if (gadget_is_dummy(gadget))
|
||||
return 0x02;
|
||||
else if (gadget_is_pxa(gadget))
|
||||
return 0x03;
|
||||
else if (gadget_is_sh(gadget))
|
||||
return 0x04;
|
||||
else if (gadget_is_sa1100(gadget))
|
||||
return 0x05;
|
||||
else if (gadget_is_goku(gadget))
|
||||
return 0x06;
|
||||
else if (gadget_is_mq11xx(gadget))
|
||||
return 0x07;
|
||||
else if (gadget_is_omap(gadget))
|
||||
return 0x08;
|
||||
else if (gadget_is_lh7a40x(gadget))
|
||||
return 0x09;
|
||||
else if (gadget_is_n9604(gadget))
|
||||
return 0x10;
|
||||
else if (gadget_is_pxa27x(gadget))
|
||||
return 0x11;
|
||||
else if (gadget_is_s3c2410(gadget))
|
||||
return 0x12;
|
||||
else if (gadget_is_at91(gadget))
|
||||
return 0x13;
|
||||
else if (gadget_is_imx(gadget))
|
||||
return 0x14;
|
||||
else if (gadget_is_musbhsfc(gadget))
|
||||
return 0x15;
|
||||
else if (gadget_is_musbhdrc(gadget))
|
||||
return 0x16;
|
||||
else if (gadget_is_mpc8272(gadget))
|
||||
return 0x17;
|
||||
else if (gadget_is_atmel_usba(gadget))
|
||||
return 0x18;
|
||||
else if (gadget_is_fsl_usb2(gadget))
|
||||
return 0x19;
|
||||
else if (gadget_is_amd5536udc(gadget))
|
||||
return 0x20;
|
||||
else if (gadget_is_m66592(gadget))
|
||||
return 0x21;
|
||||
else if (gadget_is_fsl_qe(gadget))
|
||||
return 0x22;
|
||||
else if (gadget_is_ci13xxx(gadget))
|
||||
return 0x23;
|
||||
else if (gadget_is_langwell(gadget))
|
||||
return 0x24;
|
||||
else if (gadget_is_r8a66597(gadget))
|
||||
return 0x25;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gadget_supports_altsettings - return true if altsettings work
|
||||
* @gadget: the gadget in question
|
||||
*/
|
||||
static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
|
||||
{
|
||||
/* PXA 21x/25x/26x has no altsettings at all */
|
||||
if (gadget_is_pxa(gadget))
|
||||
return false;
|
||||
|
||||
/* PXA 27x and 3xx have *broken* altsetting support */
|
||||
if (gadget_is_pxa27x(gadget))
|
||||
return false;
|
||||
|
||||
/* SH3 hardware just doesn't do altsettings */
|
||||
if (gadget_is_sh(gadget))
|
||||
return false;
|
||||
|
||||
/* Everything else is *presumably* fine ... */
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* __GADGET_CHIPS_H */
|
249
brick/kernel/source/am1808.h
Executable file
249
brick/kernel/source/am1808.h
Executable file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef AM1808_H_
|
||||
#define AM1808_H_
|
||||
|
||||
#ifndef PCASM
|
||||
#include <mach/da8xx.h>
|
||||
#else
|
||||
#define __iomem
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
GP0_0,GP0_1,GP0_2,GP0_3,GP0_4,GP0_5,GP0_6,GP0_7,GP0_8,GP0_9,GP0_10,GP0_11,GP0_12,GP0_13,GP0_14,GP0_15,
|
||||
GP1_0,GP1_1,GP1_2,GP1_3,GP1_4,GP1_5,GP1_6,GP1_7,GP1_8,GP1_9,GP1_10,GP1_11,GP1_12,GP1_13,GP1_14,GP1_15,
|
||||
GP2_0,GP2_1,GP2_2,GP2_3,GP2_4,GP2_5,GP2_6,GP2_7,GP2_8,GP2_9,GP2_10,GP2_11,GP2_12,GP2_13,GP2_14,GP2_15,
|
||||
GP3_0,GP3_1,GP3_2,GP3_3,GP3_4,GP3_5,GP3_6,GP3_7,GP3_8,GP3_9,GP3_10,GP3_11,GP3_12,GP3_13,GP3_14,GP3_15,
|
||||
GP4_0,GP4_1,GP4_2,GP4_3,GP4_4,GP4_5,GP4_6,GP4_7,GP4_8,GP4_9,GP4_10,GP4_11,GP4_12,GP4_13,GP4_14,GP4_15,
|
||||
GP5_0,GP5_1,GP5_2,GP5_3,GP5_4,GP5_5,GP5_6,GP5_7,GP5_8,GP5_9,GP5_10,GP5_11,GP5_12,GP5_13,GP5_14,GP5_15,
|
||||
GP6_0,GP6_1,GP6_2,GP6_3,GP6_4,GP6_5,GP6_6,GP6_7,GP6_8,GP6_9,GP6_10,GP6_11,GP6_12,GP6_13,GP6_14,GP6_15,
|
||||
GP7_0,GP7_1,GP7_2,GP7_3,GP7_4,GP7_5,GP7_6,GP7_7,GP7_8,GP7_9,GP7_10,GP7_11,GP7_12,GP7_13,GP7_14,GP7_15,
|
||||
GP8_0,GP8_1,GP8_2,GP8_3,GP8_4,GP8_5,GP8_6,GP8_7,GP8_8,GP8_9,GP8_10,GP8_11,GP8_12,GP8_13,GP8_14,GP8_15,
|
||||
NO_OF_GPIOS,
|
||||
UART0_TXD,UART0_RXD,UART1_TXD,UART1_RXD,
|
||||
SPI0_MOSI,SPI0_MISO,SPI0_SCL,SPI0_CS,
|
||||
SPI1_MOSI,SPI1_MISO,SPI1_SCL,SPI1_CS,
|
||||
EPWM1A,EPWM1B,APWM0,APWM1,EPWM0B,AXR3,AXR4
|
||||
};
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int Pin;
|
||||
u16 MuxReg;
|
||||
u32 Mask;
|
||||
u32 Mode;
|
||||
}
|
||||
MRM;
|
||||
|
||||
MRM MuxRegMap[] =
|
||||
{ // Pin MuxReg Mask Mode
|
||||
|
||||
{ GP0_1 , 1, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP0_2 , 1, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP0_3 , 1, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP0_4 , 1, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP0_5 , 1, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP0_6 , 1, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP0_7 , 1, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP0_11, 0, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP0_12, 0, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP0_13, 0, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP0_14, 0, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP0_15, 0, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP1_0 , 4, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP1_8 , 3, 0xFFFFFFF0, 0x00000004 },
|
||||
|
||||
{ GP1_9, 2, 0xF0FFFFFF, 0x04000000 },
|
||||
{ GP1_10, 2, 0xFF0FFFFF, 0x00400000 },
|
||||
{ GP1_11, 2, 0xFFF0FFFF, 0x00040000 },
|
||||
{ GP1_12, 2, 0xFFFF0FFF, 0x00004000 },
|
||||
{ GP1_13, 2, 0xFFFFF0FF, 0x00000400 },
|
||||
{ GP1_14, 2, 0xFFFFFF0F, 0x00000040 },
|
||||
{ GP1_15, 2, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP2_0, 6, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP2_1, 6, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP2_2, 6, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP2_3, 6, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP2_4, 6, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP2_5, 6, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP2_6, 6, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP2_7, 6, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP2_8, 5, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP2_9, 5, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP2_10, 5, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP2_11, 5, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP2_12, 5, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP2_13, 5, 0xFFFFF0FF, 0x00000800 },
|
||||
|
||||
{ GP3_0, 8, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP3_1 , 8, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP3_2, 8, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP3_3, 8, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP3_4, 8, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP3_5, 8, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP3_6, 8, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP3_7, 8, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP3_8, 7, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP3_9, 7, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP3_10, 7, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP3_11, 7, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP3_12, 7, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP3_13, 7, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP3_14, 7, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP3_15, 7, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP4_1, 10, 0xF0FFFFFF, 0x08000000 },
|
||||
|
||||
{ GP4_8, 9, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP4_9, 9, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP4_10, 9, 0xFF0FFFFF, 0x00800000 },
|
||||
|
||||
{ GP4_12, 9, 0xFFFF0FFF, 0x00008000 },
|
||||
|
||||
{ GP4_14, 9, 0xFFFFFF0F, 0x00000080 },
|
||||
|
||||
{ GP5_0, 12, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP5_1, 12, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP5_2, 12, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP5_3, 12, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP5_4, 12, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP5_5, 12, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP5_6, 12, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP5_7, 12, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP5_8, 11, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP5_9, 11, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP5_10, 11, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP5_11, 11, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP5_12, 11, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP5_13, 11, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP5_14, 11, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP5_15, 11, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP6_0 , 19, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP6_1, 19, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP6_2, 19, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP6_3, 19, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP6_4, 19, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP6_5, 16, 0xFFFFFF0F, 0x00000080 },
|
||||
|
||||
{ GP6_6, 14, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP6_7, 14, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP6_8, 13, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP6_9, 13, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP6_10, 13, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP6_11, 13, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP6_12, 13, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP6_13, 13, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP6_14, 13, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP6_15, 13, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP7_4, 17, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP7_8, 17, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP7_9, 17, 0xFFFFFFF0, 0x00000008 },
|
||||
{ GP7_10, 16, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP7_11, 16, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP7_12, 16, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP7_13, 16, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP7_14, 16, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP7_15, 16, 0xFFFFF0FF, 0x00000800 },
|
||||
|
||||
{ GP8_2 , 3 , 0xF0FFFFFF, 0x04000000 },
|
||||
{ GP8_3 , 3 , 0xFF0FFFFF, 0x00400000 },
|
||||
{ GP8_5 , 3 , 0xFFFF0FFF, 0x00004000 },
|
||||
{ GP8_6 , 3 , 0xFFFFF0FF, 0x00000400 },
|
||||
{ GP8_8 , 19, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP8_9 , 19, 0xFFFFFFF0, 0x00000008 },
|
||||
{ GP8_10, 18, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP8_11, 18, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP8_12, 18, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP8_13, 18, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP8_14, 18, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP8_15, 18, 0xFFFFF0FF, 0x00000800 },
|
||||
|
||||
|
||||
{ UART0_TXD, 3, 0xFF0FFFFF, 0x00200000 },
|
||||
{ UART0_RXD, 3, 0xFFF0FFFF, 0x00020000 },
|
||||
|
||||
{ UART1_TXD, 4, 0x0FFFFFFF, 0x20000000 },
|
||||
{ UART1_RXD, 4, 0xF0FFFFFF, 0x02000000 },
|
||||
|
||||
{ SPI0_MOSI, 3, 0xFFFF0FFF, 0x00001000 },
|
||||
{ SPI0_MISO, 3, 0xFFFFF0FF, 0x00000100 },
|
||||
{ SPI0_SCL, 3, 0xFFFFFFF0, 0x00000001 },
|
||||
{ SPI0_CS, 3, 0xF0FFFFFF, 0x01000000 },
|
||||
|
||||
{ SPI1_MOSI, 5, 0xFF0FFFFF, 0x00100000 },
|
||||
{ SPI1_MISO, 5, 0xFFF0FFFF, 0x00010000 },
|
||||
{ SPI1_SCL, 5, 0xFFFFF0FF, 0x00000100 },
|
||||
{ SPI1_CS, 5, 0xFFFF0FFF, 0x00008000 },
|
||||
|
||||
{ EPWM1A, 5, 0xFFFFFFF0, 0x00000002 },
|
||||
{ EPWM1B, 5, 0xFFFFFF0F, 0x00000020 },
|
||||
{ APWM0, 2, 0x0FFFFFFF, 0x20000000 },
|
||||
{ APWM1, 1, 0x0FFFFFFF, 0x40000000 },
|
||||
{ EPWM0B, 3, 0xFFFFFF0F, 0x00000020 },
|
||||
|
||||
{ AXR3, 2, 0xFFF0FFFF, 0x00010000 },
|
||||
{ AXR4, 2, 0xFFFF0FFF, 0x00001000 },
|
||||
|
||||
{-1 }
|
||||
};
|
||||
|
||||
typedef struct gpio_controller *__iomem GPIOC;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int Pin; // GPIO pin number
|
||||
GPIOC pGpio; // GPIO bank base address
|
||||
u32 Mask; // GPIO pin mask
|
||||
}
|
||||
INPIN;
|
||||
|
||||
#define REGUnlock {\
|
||||
iowrite32(0x83E70B13,da8xx_syscfg0_base + 0x38);\
|
||||
iowrite32(0x95A4F1E0,da8xx_syscfg0_base + 0x3C);\
|
||||
}
|
||||
|
||||
#define REGLock {\
|
||||
iowrite32(0x00000000,da8xx_syscfg0_base + 0x38);\
|
||||
iowrite32(0x00000000,da8xx_syscfg0_base + 0x3C);\
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#else
|
||||
|
||||
extern MRM MuxRegMap[];
|
||||
|
||||
#endif /* AM1808_H_ */
|
||||
|
||||
|
1744
brick/kernel/source/bytecodes.h
Normal file
1744
brick/kernel/source/bytecodes.h
Normal file
File diff suppressed because it is too large
Load Diff
81
brick/kernel/source/c_branch.h
Normal file
81
brick/kernel/source/c_branch.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef C_BRANCH_H_
|
||||
#define C_BRANCH_H_
|
||||
|
||||
void cBranchJr(void);
|
||||
|
||||
void cBranchJrFalse(void);
|
||||
|
||||
void cBranchJrTrue(void);
|
||||
|
||||
void cBranchJrNan(void);
|
||||
|
||||
void cBranchJrLt8(void);
|
||||
|
||||
void cBranchJrLt16(void);
|
||||
|
||||
void cBranchJrLt32(void);
|
||||
|
||||
void cBranchJrLtF(void);
|
||||
|
||||
void cBranchJrGt8(void);
|
||||
|
||||
void cBranchJrGt16(void);
|
||||
|
||||
void cBranchJrGt32(void);
|
||||
|
||||
void cBranchJrGtF(void);
|
||||
|
||||
void cBranchJrLtEq8(void);
|
||||
|
||||
void cBranchJrLtEq16(void);
|
||||
|
||||
void cBranchJrLtEq32(void);
|
||||
|
||||
void cBranchJrLtEqF(void);
|
||||
|
||||
void cBranchJrGtEq8(void);
|
||||
|
||||
void cBranchJrGtEq16(void);
|
||||
|
||||
void cBranchJrGtEq32(void);
|
||||
|
||||
void cBranchJrGtEqF(void);
|
||||
|
||||
void cBranchJrEq8(void);
|
||||
|
||||
void cBranchJrEq16(void);
|
||||
|
||||
void cBranchJrEq32(void);
|
||||
|
||||
void cBranchJrEqF(void);
|
||||
|
||||
void cBranchJrNEq8(void);
|
||||
|
||||
void cBranchJrNEq16(void);
|
||||
|
||||
void cBranchJrNEq32(void);
|
||||
|
||||
void cBranchJrNEqF(void);
|
||||
|
||||
#endif /* C_BRANCH_H_ */
|
81
brick/kernel/source/c_compare.h
Normal file
81
brick/kernel/source/c_compare.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef C_COMPARE_H_
|
||||
#define C_COMPARE_H_
|
||||
|
||||
void cCompareLt8(void);
|
||||
|
||||
void cCompareLt16(void);
|
||||
|
||||
void cCompareLt32(void);
|
||||
|
||||
void cCompareLtF(void);
|
||||
|
||||
void cCompareGt8(void);
|
||||
|
||||
void cCompareGt16(void);
|
||||
|
||||
void cCompareGt32(void);
|
||||
|
||||
void cCompareGtF(void);
|
||||
|
||||
void cCompareEq8(void);
|
||||
|
||||
void cCompareEq16(void);
|
||||
|
||||
void cCompareEq32(void);
|
||||
|
||||
void cCompareEqF(void);
|
||||
|
||||
void cCompareNEq8(void);
|
||||
|
||||
void cCompareNEq16(void);
|
||||
|
||||
void cCompareNEq32(void);
|
||||
|
||||
void cCompareNEqF(void);
|
||||
|
||||
void cCompareLtEq8(void);
|
||||
|
||||
void cCompareLtEq16(void);
|
||||
|
||||
void cCompareLtEq32(void);
|
||||
|
||||
void cCompareLtEqF(void);
|
||||
|
||||
void cCompareGtEq8(void);
|
||||
|
||||
void cCompareGtEq16(void);
|
||||
|
||||
void cCompareGtEq32(void);
|
||||
|
||||
void cCompareGtEqF(void);
|
||||
|
||||
void cCompareSelect8(void);
|
||||
|
||||
void cCompareSelect16(void);
|
||||
|
||||
void cCompareSelect32(void);
|
||||
|
||||
void cCompareSelectF(void);
|
||||
|
||||
#endif /* C_COMPARE_H_ */
|
88
brick/kernel/source/c_math.h
Normal file
88
brick/kernel/source/c_math.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef C_MATH_H_
|
||||
#define C_MATH_H_
|
||||
|
||||
#define DegToRad(D) (D * 0.0174532925)
|
||||
|
||||
#define RadToDeg(R) (R * 57.2957795)
|
||||
|
||||
|
||||
void cMathAdd8(void);
|
||||
|
||||
void cMathAdd16(void);
|
||||
|
||||
void cMathAdd32(void);
|
||||
|
||||
void cMathAddF(void);
|
||||
|
||||
void cMathSub8(void);
|
||||
|
||||
void cMathSub16(void);
|
||||
|
||||
void cMathSub32(void);
|
||||
|
||||
void cMathSubF(void);
|
||||
|
||||
void cMathMul8(void);
|
||||
|
||||
void cMathMul16(void);
|
||||
|
||||
void cMathMul32(void);
|
||||
|
||||
void cMathMulF(void);
|
||||
|
||||
void cMathDiv8(void);
|
||||
|
||||
void cMathDiv16(void);
|
||||
|
||||
void cMathDiv32(void);
|
||||
|
||||
void cMathDivF(void);
|
||||
|
||||
void cMathOr8(void);
|
||||
|
||||
void cMathOr16(void);
|
||||
|
||||
void cMathOr32(void);
|
||||
|
||||
void cMathAnd8(void);
|
||||
|
||||
void cMathAnd16(void);
|
||||
|
||||
void cMathAnd32(void);
|
||||
|
||||
void cMathXor8(void);
|
||||
|
||||
void cMathXor16(void);
|
||||
|
||||
void cMathXor32(void);
|
||||
|
||||
void cMathRl8(void);
|
||||
|
||||
void cMathRl16(void);
|
||||
|
||||
void cMathRl32(void);
|
||||
|
||||
void cMath(void);
|
||||
|
||||
#endif /* C_MATH_H_ */
|
76
brick/kernel/source/c_move.h
Normal file
76
brick/kernel/source/c_move.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef C_MOVE_H_
|
||||
#define C_MOVE_H_
|
||||
|
||||
void cMove8to8(void);
|
||||
|
||||
void cMove8to16(void);
|
||||
|
||||
void cMove8to32(void);
|
||||
|
||||
void cMove8toF(void);
|
||||
|
||||
void cMove16to8(void);
|
||||
|
||||
void cMove16to16(void);
|
||||
|
||||
void cMove16to32(void);
|
||||
|
||||
void cMove16toF(void);
|
||||
|
||||
void cMove32to8(void);
|
||||
|
||||
void cMove32to16(void);
|
||||
|
||||
void cMove32to32(void);
|
||||
|
||||
void cMove32toF(void);
|
||||
|
||||
void cMoveFto8(void);
|
||||
|
||||
void cMoveFto16(void);
|
||||
|
||||
void cMoveFto32(void);
|
||||
|
||||
void cMoveFtoF(void);
|
||||
|
||||
void cMoveInitBytes(void);
|
||||
|
||||
void cMoveRead8(void);
|
||||
|
||||
void cMoveRead16(void);
|
||||
|
||||
void cMoveRead32(void);
|
||||
|
||||
void cMoveReadF(void);
|
||||
|
||||
void cMoveWrite8(void);
|
||||
|
||||
void cMoveWrite16(void);
|
||||
|
||||
void cMoveWrite32(void);
|
||||
|
||||
void cMoveWriteF(void);
|
||||
|
||||
|
||||
#endif /* C_MOVE_H_ */
|
38
brick/kernel/source/c_timer.h
Normal file
38
brick/kernel/source/c_timer.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef C_TIMER_H_
|
||||
#define C_TIMER_H_
|
||||
|
||||
#if (HARDWARE != SIMULATION)
|
||||
ULONG cTimerGetuS(void);
|
||||
ULONG cTimerGetmS(void);
|
||||
#endif
|
||||
|
||||
void cTimerWait(void);
|
||||
|
||||
void cTimerReady(void);
|
||||
|
||||
void cTimerRead(void);
|
||||
|
||||
void cTimerReaduS(void);
|
||||
|
||||
#endif /* C_TIMER_H_ */
|
1566
brick/kernel/source/lms2012.h
Executable file
1566
brick/kernel/source/lms2012.h
Executable file
File diff suppressed because it is too large
Load Diff
195
brick/kernel/source/lmstypes.h
Normal file
195
brick/kernel/source/lmstypes.h
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* As a special exception, if other files instantiate templates or use macros or
|
||||
* inline functions from this file, or you compile this file and link it with
|
||||
* other works to produce a work based on this file, this file does not by itself
|
||||
* cause the resulting work to be covered by the GNU General Public License.
|
||||
* However the source code for this file must still be made available in accordance
|
||||
* with section (3) of the GNU General Public License.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LMSTYPES_H_
|
||||
#define LMSTYPES_H_
|
||||
|
||||
// BASIC DATA TYPES
|
||||
|
||||
#ifndef LEGO_SIMULATION
|
||||
|
||||
typedef unsigned char UBYTE; //!< Basic Type used to symbolise 8 bit unsigned values
|
||||
typedef unsigned short UWORD; //!< Basic Type used to symbolise 16 bit unsigned values
|
||||
typedef unsigned int ULONG; //!< Basic Type used to symbolise 32 bit unsigned values
|
||||
|
||||
typedef signed char SBYTE; //!< Basic Type used to symbolise 8 bit signed values
|
||||
typedef signed short SWORD; //!< Basic Type used to symbolise 16 bit signed values
|
||||
typedef signed int SLONG; //!< Basic Type used to symbolise 32 bit signed values
|
||||
|
||||
typedef float FLOAT; //!< Basic Type used to symbolise 32 bit floating point values
|
||||
|
||||
#define LFILE FILE
|
||||
|
||||
#else
|
||||
|
||||
#include <Base/BasicTypes.h>
|
||||
#include <VMCalls.h>
|
||||
|
||||
typedef LEGO::UInt8 UBYTE; //!< Basic Type used to symbolise 8 bit unsigned values
|
||||
typedef LEGO::UInt16 UWORD; //!< Basic Type used to symbolise 16 bit unsigned values
|
||||
typedef unsigned long ULONG; //!< Basic Type used to symbolise 32 bit unsigned values
|
||||
|
||||
|
||||
typedef LEGO::Int8 SBYTE; //!< Basic Type used to symbolise 8 bit signed values
|
||||
typedef LEGO::Int16 SWORD; //!< Basic Type used to symbolise 16 bit signed values
|
||||
typedef LEGO::Int32 SLONG; //!< Basic Type used to symbolise 32 bit signed values
|
||||
|
||||
typedef LEGO::Real32 FLOAT; //!< Basic Type used to symbolise 32 bit floating point values
|
||||
|
||||
#endif
|
||||
|
||||
// VM DATA TYPES
|
||||
|
||||
typedef SBYTE DATA8; //!< VM Type for 1 byte signed value
|
||||
typedef SWORD DATA16; //!< VM Type for 2 byte signed value
|
||||
typedef SLONG DATA32; //!< VM Type for 4 byte signed value
|
||||
typedef FLOAT DATAF; //!< VM Type for 4 byte floating point value
|
||||
|
||||
// VM VARIABLE TYPES
|
||||
|
||||
typedef UBYTE VARDATA; //!< Variable base type
|
||||
typedef UBYTE IMGDATA; //!< Image base type
|
||||
|
||||
typedef UWORD PRGID; //!< Program id type
|
||||
|
||||
typedef UWORD OBJID; //!< Object id type
|
||||
typedef IMGDATA* IP; //!< Instruction pointer type
|
||||
typedef VARDATA* LP; //!< Local variable pointer type
|
||||
typedef VARDATA* GP; //!< global variable pointer type
|
||||
|
||||
typedef ULONG IMINDEX; //!< ImageData index type
|
||||
typedef ULONG GBINDEX; //!< GlobalBytes index type
|
||||
typedef ULONG LBINDEX; //!< LocalBytes index type
|
||||
typedef UWORD TRIGGER; //!< TriggerCount type
|
||||
typedef UBYTE PARS; //!< NoOfParameters type
|
||||
typedef SLONG IMOFFS; //!< ImageData offset type
|
||||
|
||||
typedef DATA16 HANDLER; //!< Memory list index
|
||||
|
||||
|
||||
|
||||
/*! \page imagelayout Image Layout
|
||||
* The image consists of three different components in this fixed order: imageheader, objectheaders and byte codes.
|
||||
*
|
||||
* The imageheader tells something about image version, filesize, no of objectheaders (objects) and no of global variable bytes.
|
||||
*
|
||||
*
|
||||
* Objectheaders contains different informations depending on the nature of the object:
|
||||
*
|
||||
*- The VMTHREAD object (former TBC_TOPVI) \n
|
||||
* - OffsetToInstructions tells were to find the corresponding byte codes (offset from image start) \n
|
||||
* - OwnerObjectId must be zero \n
|
||||
* - TriggerCount is used but must be zero \n
|
||||
* - LocalBytes describes the number of bytes for local variables \n
|
||||
*
|
||||
*- The SUBCALL object (former TBC_VI and TBC_VI_ALIAS) \n
|
||||
* - OffsetToInstructions tells were to find the corresponding byte codes (if alias this is equal to mother object) \n
|
||||
* - OwnerObjectId must be zero \n
|
||||
* - TriggerCount is used and must be one \n
|
||||
* - LocalBytes describes the number of bytes for local variables \n
|
||||
*
|
||||
*- The BLOCK object (former CLUMP) \n
|
||||
* - OffsetToInstructions tells were to find the corresponding byte codes (offset from image start) \n
|
||||
* - OwnerObjectId is equal to object id it belongs to (not equal to zero) \n
|
||||
* - TriggerCount is used to determine how many triggers needed before the BLOCK object is activated \n
|
||||
* - LocalBytes must be zero (locals are defined in the owner object) \n
|
||||
*
|
||||
* Byte codes are described in a different section.
|
||||
*
|
||||
* Little Endian are used (addresses and data are represented with LSB on lowest address and MSB on highest address).
|
||||
*
|
||||
* Offset to instructions is number of bytes from start of image to start of object instructions.
|
||||
*
|
||||
* Index to global variables are byte based and counted from start of globals (zero based).
|
||||
*
|
||||
* Index to local variables are byte based and counted from start of object locals (zero based).
|
||||
*
|
||||
* Object ID's is not zero based - First object (VMTHEAD) is named 1.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \page imagelayout
|
||||
*
|
||||
* FILE layout (aligned)
|
||||
*
|
||||
*- IMGHEAD (aligned)
|
||||
* - Sign (4 bytes)
|
||||
* - ImageSize (4 bytes)
|
||||
* - VersionInfo (2 bytes)
|
||||
* - NumberOfObjects (2 bytes)
|
||||
* - GlobalBytes (4 bytes)
|
||||
*/
|
||||
|
||||
/*! \struct IMGHEAD
|
||||
* Image header
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UBYTE Sign[4]; //!< Place holder for the file type identifier
|
||||
IMINDEX ImageSize; //!< Image size
|
||||
UWORD VersionInfo; //!< Version identifier
|
||||
OBJID NumberOfObjects; //!< Total number of objects in image
|
||||
GBINDEX GlobalBytes; //!< Number of bytes to allocate for global variables
|
||||
}
|
||||
IMGHEAD;
|
||||
|
||||
/*! \page imagelayout
|
||||
*
|
||||
*- OBJHEAD (aligned)
|
||||
* - OffsetToInstructions (4 bytes)
|
||||
* - OwnerObjectId (2 bytes)
|
||||
* - TriggerCount (2 bytes)
|
||||
* - LocalBytes (4 bytes)
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \struct OBJHEAD
|
||||
* Object header used for all types of objects (VMTHREAD, SUBCALL, BLOCK and ALIAS)
|
||||
*/
|
||||
typedef struct // Object header
|
||||
{
|
||||
IP OffsetToInstructions; //!< Offset to instructions from image start
|
||||
OBJID OwnerObjectId; //!< Used by BLOCK's to hold the owner id
|
||||
TRIGGER TriggerCount; //!< Used to determine how many triggers needed before the BLOCK object is activated
|
||||
LBINDEX LocalBytes; //!< Number of bytes to allocate for local variables
|
||||
}
|
||||
OBJHEAD;
|
||||
|
||||
|
||||
/*! \struct LABEL
|
||||
* Label data hold information used for labels
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
IMINDEX Addr; //!< Offset to breakpoint address from image start
|
||||
}
|
||||
LABEL;
|
||||
|
||||
|
||||
#endif /* LMSTYPES_H_ */
|
56
brick/kernel/source/validate.h
Normal file
56
brick/kernel/source/validate.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef VALIDATE_H_
|
||||
#define VALIDATE_H_
|
||||
|
||||
RESULT cValidateInit(void);
|
||||
|
||||
RESULT cValidateExit(void);
|
||||
|
||||
RESULT cValidateDisassemble(IP pI,IMINDEX *pIndex,LABEL *pLabel);
|
||||
|
||||
RESULT cValidateProgram(PRGID PrgId,IP pI,LABEL *pLabel,DATA8 Disassemble);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//*****************************************************************************
|
||||
// Validate Global variables
|
||||
//*****************************************************************************
|
||||
|
||||
int Row;
|
||||
IMINDEX ValidateErrorIndex;
|
||||
}
|
||||
VALIDATE_GLOBALS;
|
||||
|
||||
#ifndef LEGO_SIMULATION
|
||||
extern VALIDATE_GLOBALS ValidateInstance;
|
||||
#else
|
||||
extern VALIDATE_GLOBALS * gValidateInstance;
|
||||
#define ValidateInstance (*gValidateInstance)
|
||||
|
||||
void setValidateInstance(VALIDATE_GLOBALS * _Instance);
|
||||
VALIDATE_GLOBALS * getValidateInstance();
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* VALIDATE_H_ */
|
780
brick/kernel/storage_common.c
Normal file
780
brick/kernel/storage_common.c
Normal file
@ -0,0 +1,780 @@
|
||||
/*
|
||||
* storage_common.c -- Common definitions for mass storage functionality
|
||||
*
|
||||
* Copyright (C) 2003-2008 Alan Stern
|
||||
* Copyeight (C) 2009 Samsung Electronics
|
||||
* Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This file requires the following identifiers used in USB strings to
|
||||
* be defined (each of type pointer to char):
|
||||
* - fsg_string_manufacturer -- name of the manufacturer
|
||||
* - fsg_string_product -- name of the product
|
||||
* - fsg_string_serial -- product's serial
|
||||
* - fsg_string_config -- name of the configuration
|
||||
* - fsg_string_interface -- name of the interface
|
||||
* The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS
|
||||
* macro is defined prior to including this file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* When FSG_NO_INTR_EP is defined fsg_fs_intr_in_desc and
|
||||
* fsg_hs_intr_in_desc objects as well as
|
||||
* FSG_FS_FUNCTION_PRE_EP_ENTRIES and FSG_HS_FUNCTION_PRE_EP_ENTRIES
|
||||
* macros are not defined.
|
||||
*
|
||||
* When FSG_NO_DEVICE_STRINGS is defined FSG_STRING_MANUFACTURER,
|
||||
* FSG_STRING_PRODUCT, FSG_STRING_SERIAL and FSG_STRING_CONFIG are not
|
||||
* defined (as well as corresponding entries in string tables are
|
||||
* missing) and FSG_STRING_INTERFACE has value of zero.
|
||||
*
|
||||
* When FSG_NO_OTG is defined fsg_otg_desc won't be defined.
|
||||
*/
|
||||
|
||||
/*
|
||||
* When FSG_BUFFHD_STATIC_BUFFER is defined when this file is included
|
||||
* the fsg_buffhd structure's buf field will be an array of FSG_BUFLEN
|
||||
* characters rather then a pointer to void.
|
||||
*/
|
||||
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
|
||||
/* Thanks to NetChip Technologies for donating this product ID.
|
||||
*
|
||||
* DO NOT REUSE THESE IDs with any other driver!! Ever!!
|
||||
* Instead: allocate your own, using normal USB-IF procedures. */
|
||||
#define FSG_VENDOR_ID 0x0525 /* NetChip */
|
||||
#define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef DEBUG
|
||||
#undef VERBOSE_DEBUG
|
||||
#undef DUMP_MSGS
|
||||
#endif /* !DEBUG */
|
||||
|
||||
#ifdef VERBOSE_DEBUG
|
||||
#define VLDBG LDBG
|
||||
#else
|
||||
#define VLDBG(lun, fmt, args...) do { } while (0)
|
||||
#endif /* VERBOSE_DEBUG */
|
||||
|
||||
#define LDBG(lun, fmt, args...) dev_dbg (&(lun)->dev, fmt, ## args)
|
||||
#define LERROR(lun, fmt, args...) dev_err (&(lun)->dev, fmt, ## args)
|
||||
#define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args)
|
||||
#define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args)
|
||||
|
||||
/* Keep those macros in sync with thos in
|
||||
* include/linux/ubs/composite.h or else GCC will complain. If they
|
||||
* are identical (the same names of arguments, white spaces in the
|
||||
* same places) GCC will allow redefinition otherwise (even if some
|
||||
* white space is removed or added) warning will be issued. No
|
||||
* checking if those symbols is defined is performed because warning
|
||||
* is desired when those macros were defined by someone else to mean
|
||||
* something else. */
|
||||
#define DBG(d, fmt, args...) dev_dbg(&(d)->gadget->dev , fmt , ## args)
|
||||
#define VDBG(d, fmt, args...) dev_vdbg(&(d)->gadget->dev , fmt , ## args)
|
||||
#define ERROR(d, fmt, args...) dev_err(&(d)->gadget->dev , fmt , ## args)
|
||||
#define WARNING(d, fmt, args...) dev_warn(&(d)->gadget->dev , fmt , ## args)
|
||||
#define INFO(d, fmt, args...) dev_info(&(d)->gadget->dev , fmt , ## args)
|
||||
|
||||
|
||||
|
||||
#ifdef DUMP_MSGS
|
||||
|
||||
# define dump_msg(fsg, /* const char * */ label, \
|
||||
/* const u8 * */ buf, /* unsigned */ length) do { \
|
||||
if (length < 512) { \
|
||||
DBG(fsg, "%s, length %u:\n", label, length); \
|
||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \
|
||||
16, 1, buf, length, 0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
# define dump_cdb(fsg) do { } while (0)
|
||||
|
||||
#else
|
||||
|
||||
# define dump_msg(fsg, /* const char * */ label, \
|
||||
/* const u8 * */ buf, /* unsigned */ length) do { } while (0)
|
||||
|
||||
# ifdef VERBOSE_DEBUG
|
||||
|
||||
# define dump_cdb(fsg) \
|
||||
print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE, \
|
||||
16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0) \
|
||||
|
||||
# else
|
||||
|
||||
# define dump_cdb(fsg) do { } while (0)
|
||||
|
||||
# endif /* VERBOSE_DEBUG */
|
||||
|
||||
#endif /* DUMP_MSGS */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* SCSI device types */
|
||||
#define TYPE_DISK 0x00
|
||||
#define TYPE_CDROM 0x05
|
||||
|
||||
/* USB protocol value = the transport method */
|
||||
#define USB_PR_CBI 0x00 /* Control/Bulk/Interrupt */
|
||||
#define USB_PR_CB 0x01 /* Control/Bulk w/o interrupt */
|
||||
#define USB_PR_BULK 0x50 /* Bulk-only */
|
||||
|
||||
/* USB subclass value = the protocol encapsulation */
|
||||
#define USB_SC_RBC 0x01 /* Reduced Block Commands (flash) */
|
||||
#define USB_SC_8020 0x02 /* SFF-8020i, MMC-2, ATAPI (CD-ROM) */
|
||||
#define USB_SC_QIC 0x03 /* QIC-157 (tape) */
|
||||
#define USB_SC_UFI 0x04 /* UFI (floppy) */
|
||||
#define USB_SC_8070 0x05 /* SFF-8070i (removable) */
|
||||
#define USB_SC_SCSI 0x06 /* Transparent SCSI */
|
||||
|
||||
/* Bulk-only data structures */
|
||||
|
||||
/* Command Block Wrapper */
|
||||
struct fsg_bulk_cb_wrap {
|
||||
__le32 Signature; /* Contains 'USBC' */
|
||||
u32 Tag; /* Unique per command id */
|
||||
__le32 DataTransferLength; /* Size of the data */
|
||||
u8 Flags; /* Direction in bit 7 */
|
||||
u8 Lun; /* LUN (normally 0) */
|
||||
u8 Length; /* Of the CDB, <= MAX_COMMAND_SIZE */
|
||||
u8 CDB[16]; /* Command Data Block */
|
||||
};
|
||||
|
||||
#define USB_BULK_CB_WRAP_LEN 31
|
||||
#define USB_BULK_CB_SIG 0x43425355 /* Spells out USBC */
|
||||
#define USB_BULK_IN_FLAG 0x80
|
||||
|
||||
/* Command Status Wrapper */
|
||||
struct bulk_cs_wrap {
|
||||
__le32 Signature; /* Should = 'USBS' */
|
||||
u32 Tag; /* Same as original command */
|
||||
__le32 Residue; /* Amount not transferred */
|
||||
u8 Status; /* See below */
|
||||
};
|
||||
|
||||
#define USB_BULK_CS_WRAP_LEN 13
|
||||
#define USB_BULK_CS_SIG 0x53425355 /* Spells out 'USBS' */
|
||||
#define USB_STATUS_PASS 0
|
||||
#define USB_STATUS_FAIL 1
|
||||
#define USB_STATUS_PHASE_ERROR 2
|
||||
|
||||
/* Bulk-only class specific requests */
|
||||
#define USB_BULK_RESET_REQUEST 0xff
|
||||
#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe
|
||||
|
||||
|
||||
/* CBI Interrupt data structure */
|
||||
struct interrupt_data {
|
||||
u8 bType;
|
||||
u8 bValue;
|
||||
};
|
||||
|
||||
#define CBI_INTERRUPT_DATA_LEN 2
|
||||
|
||||
/* CBI Accept Device-Specific Command request */
|
||||
#define USB_CBI_ADSC_REQUEST 0x00
|
||||
|
||||
|
||||
/* Length of a SCSI Command Data Block */
|
||||
#define MAX_COMMAND_SIZE 16
|
||||
|
||||
/* SCSI commands that we recognize */
|
||||
#define SC_FORMAT_UNIT 0x04
|
||||
#define SC_INQUIRY 0x12
|
||||
#define SC_MODE_SELECT_6 0x15
|
||||
#define SC_MODE_SELECT_10 0x55
|
||||
#define SC_MODE_SENSE_6 0x1a
|
||||
#define SC_MODE_SENSE_10 0x5a
|
||||
#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
|
||||
#define SC_READ_6 0x08
|
||||
#define SC_READ_10 0x28
|
||||
#define SC_READ_12 0xa8
|
||||
#define SC_READ_CAPACITY 0x25
|
||||
#define SC_READ_FORMAT_CAPACITIES 0x23
|
||||
#define SC_READ_HEADER 0x44
|
||||
#define SC_READ_TOC 0x43
|
||||
#define SC_RELEASE 0x17
|
||||
#define SC_REQUEST_SENSE 0x03
|
||||
#define SC_RESERVE 0x16
|
||||
#define SC_SEND_DIAGNOSTIC 0x1d
|
||||
#define SC_START_STOP_UNIT 0x1b
|
||||
#define SC_SYNCHRONIZE_CACHE 0x35
|
||||
#define SC_TEST_UNIT_READY 0x00
|
||||
#define SC_VERIFY 0x2f
|
||||
#define SC_WRITE_6 0x0a
|
||||
#define SC_WRITE_10 0x2a
|
||||
#define SC_WRITE_12 0xaa
|
||||
|
||||
/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
|
||||
#define SS_NO_SENSE 0
|
||||
#define SS_COMMUNICATION_FAILURE 0x040800
|
||||
#define SS_INVALID_COMMAND 0x052000
|
||||
#define SS_INVALID_FIELD_IN_CDB 0x052400
|
||||
#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100
|
||||
#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500
|
||||
#define SS_MEDIUM_NOT_PRESENT 0x023a00
|
||||
#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302
|
||||
#define SS_NOT_READY_TO_READY_TRANSITION 0x062800
|
||||
#define SS_RESET_OCCURRED 0x062900
|
||||
#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900
|
||||
#define SS_UNRECOVERED_READ_ERROR 0x031100
|
||||
#define SS_WRITE_ERROR 0x030c02
|
||||
#define SS_WRITE_PROTECTED 0x072700
|
||||
|
||||
#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */
|
||||
#define ASC(x) ((u8) ((x) >> 8))
|
||||
#define ASCQ(x) ((u8) (x))
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
struct fsg_lun {
|
||||
struct file *filp;
|
||||
loff_t file_length;
|
||||
loff_t num_sectors;
|
||||
|
||||
unsigned int initially_ro:1;
|
||||
unsigned int ro:1;
|
||||
unsigned int removable:1;
|
||||
unsigned int cdrom:1;
|
||||
unsigned int prevent_medium_removal:1;
|
||||
unsigned int registered:1;
|
||||
unsigned int info_valid:1;
|
||||
|
||||
u32 sense_data;
|
||||
u32 sense_data_info;
|
||||
u32 unit_attention_data;
|
||||
|
||||
struct device dev;
|
||||
};
|
||||
|
||||
#define fsg_lun_is_open(curlun) ((curlun)->filp != NULL)
|
||||
|
||||
static struct fsg_lun *fsg_lun_from_dev(struct device *dev)
|
||||
{
|
||||
return container_of(dev, struct fsg_lun, dev);
|
||||
}
|
||||
|
||||
|
||||
/* Big enough to hold our biggest descriptor */
|
||||
#define EP0_BUFSIZE 256
|
||||
#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */
|
||||
|
||||
/* Number of buffers we will use. 2 is enough for double-buffering */
|
||||
#define FSG_NUM_BUFFERS 2
|
||||
|
||||
/* Default size of buffer length. */
|
||||
#define FSG_BUFLEN ((u32)16384)
|
||||
|
||||
/* Maximal number of LUNs supported in mass storage function */
|
||||
#define FSG_MAX_LUNS 8
|
||||
|
||||
enum fsg_buffer_state {
|
||||
BUF_STATE_EMPTY = 0,
|
||||
BUF_STATE_FULL,
|
||||
BUF_STATE_BUSY
|
||||
};
|
||||
|
||||
struct fsg_buffhd {
|
||||
#ifdef FSG_BUFFHD_STATIC_BUFFER
|
||||
char buf[FSG_BUFLEN];
|
||||
#else
|
||||
void *buf;
|
||||
#endif
|
||||
enum fsg_buffer_state state;
|
||||
struct fsg_buffhd *next;
|
||||
|
||||
/* The NetChip 2280 is faster, and handles some protocol faults
|
||||
* better, if we don't submit any short bulk-out read requests.
|
||||
* So we will record the intended request length here. */
|
||||
unsigned int bulk_out_intended_length;
|
||||
|
||||
struct usb_request *inreq;
|
||||
int inreq_busy;
|
||||
struct usb_request *outreq;
|
||||
int outreq_busy;
|
||||
};
|
||||
|
||||
enum fsg_state {
|
||||
/* This one isn't used anywhere */
|
||||
FSG_STATE_COMMAND_PHASE = -10,
|
||||
FSG_STATE_DATA_PHASE,
|
||||
FSG_STATE_STATUS_PHASE,
|
||||
|
||||
FSG_STATE_IDLE = 0,
|
||||
FSG_STATE_ABORT_BULK_OUT,
|
||||
FSG_STATE_RESET,
|
||||
FSG_STATE_INTERFACE_CHANGE,
|
||||
FSG_STATE_CONFIG_CHANGE,
|
||||
FSG_STATE_DISCONNECT,
|
||||
FSG_STATE_EXIT,
|
||||
FSG_STATE_TERMINATED
|
||||
};
|
||||
|
||||
enum data_direction {
|
||||
DATA_DIR_UNKNOWN = 0,
|
||||
DATA_DIR_FROM_HOST,
|
||||
DATA_DIR_TO_HOST,
|
||||
DATA_DIR_NONE
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static inline u32 get_unaligned_be24(u8 *buf)
|
||||
{
|
||||
return 0xffffff & (u32) get_unaligned_be32(buf - 1);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
enum {
|
||||
#ifndef FSG_NO_DEVICE_STRINGS
|
||||
FSG_STRING_MANUFACTURER = 1,
|
||||
FSG_STRING_PRODUCT,
|
||||
FSG_STRING_SERIAL,
|
||||
FSG_STRING_CONFIG,
|
||||
#endif
|
||||
FSG_STRING_INTERFACE
|
||||
};
|
||||
|
||||
|
||||
#ifndef FSG_NO_OTG
|
||||
static struct usb_otg_descriptor
|
||||
fsg_otg_desc = {
|
||||
.bLength = sizeof fsg_otg_desc,
|
||||
.bDescriptorType = USB_DT_OTG,
|
||||
|
||||
.bmAttributes = USB_OTG_SRP,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* There is only one interface. */
|
||||
|
||||
static struct usb_interface_descriptor
|
||||
fsg_intf_desc = {
|
||||
.bLength = sizeof fsg_intf_desc,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
|
||||
.bNumEndpoints = 2, /* Adjusted during fsg_bind() */
|
||||
.bInterfaceClass = USB_CLASS_MASS_STORAGE,
|
||||
.bInterfaceSubClass = USB_SC_SCSI, /* Adjusted during fsg_bind() */
|
||||
.bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */
|
||||
.iInterface = FSG_STRING_INTERFACE,
|
||||
};
|
||||
|
||||
/* Three full-speed endpoint descriptors: bulk-in, bulk-out,
|
||||
* and interrupt-in. */
|
||||
|
||||
static struct usb_endpoint_descriptor
|
||||
fsg_fs_bulk_in_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
.bEndpointAddress = USB_DIR_IN,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
||||
/* wMaxPacketSize set by autoconfiguration */
|
||||
};
|
||||
|
||||
static struct usb_endpoint_descriptor
|
||||
fsg_fs_bulk_out_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
.bEndpointAddress = USB_DIR_OUT,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
||||
/* wMaxPacketSize set by autoconfiguration */
|
||||
};
|
||||
|
||||
#ifndef FSG_NO_INTR_EP
|
||||
|
||||
static struct usb_endpoint_descriptor
|
||||
fsg_fs_intr_in_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
.bEndpointAddress = USB_DIR_IN,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(2),
|
||||
.bInterval = 32, /* frames -> 32 ms */
|
||||
};
|
||||
|
||||
#ifndef FSG_NO_OTG
|
||||
# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 2
|
||||
#else
|
||||
# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
static struct usb_descriptor_header *fsg_fs_function[] = {
|
||||
#ifndef FSG_NO_OTG
|
||||
(struct usb_descriptor_header *) &fsg_otg_desc,
|
||||
#endif
|
||||
(struct usb_descriptor_header *) &fsg_intf_desc,
|
||||
(struct usb_descriptor_header *) &fsg_fs_bulk_in_desc,
|
||||
(struct usb_descriptor_header *) &fsg_fs_bulk_out_desc,
|
||||
#ifndef FSG_NO_INTR_EP
|
||||
(struct usb_descriptor_header *) &fsg_fs_intr_in_desc,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* USB 2.0 devices need to expose both high speed and full speed
|
||||
* descriptors, unless they only run at full speed.
|
||||
*
|
||||
* That means alternate endpoint descriptors (bigger packets)
|
||||
* and a "device qualifier" ... plus more construction options
|
||||
* for the config descriptor.
|
||||
*/
|
||||
static struct usb_endpoint_descriptor
|
||||
fsg_hs_bulk_in_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
/* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
|
||||
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
||||
.wMaxPacketSize = cpu_to_le16(512),
|
||||
};
|
||||
|
||||
static struct usb_endpoint_descriptor
|
||||
fsg_hs_bulk_out_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
/* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
|
||||
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
||||
.wMaxPacketSize = cpu_to_le16(512),
|
||||
.bInterval = 1, /* NAK every 1 uframe */
|
||||
};
|
||||
|
||||
#ifndef FSG_NO_INTR_EP
|
||||
|
||||
static struct usb_endpoint_descriptor
|
||||
fsg_hs_intr_in_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(2),
|
||||
.bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */
|
||||
};
|
||||
|
||||
#ifndef FSG_NO_OTG
|
||||
# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 2
|
||||
#else
|
||||
# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
static struct usb_descriptor_header *fsg_hs_function[] = {
|
||||
#ifndef FSG_NO_OTG
|
||||
(struct usb_descriptor_header *) &fsg_otg_desc,
|
||||
#endif
|
||||
(struct usb_descriptor_header *) &fsg_intf_desc,
|
||||
(struct usb_descriptor_header *) &fsg_hs_bulk_in_desc,
|
||||
(struct usb_descriptor_header *) &fsg_hs_bulk_out_desc,
|
||||
#ifndef FSG_NO_INTR_EP
|
||||
(struct usb_descriptor_header *) &fsg_hs_intr_in_desc,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* Maxpacket and other transfer characteristics vary by speed. */
|
||||
static struct usb_endpoint_descriptor *
|
||||
fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
|
||||
struct usb_endpoint_descriptor *hs)
|
||||
{
|
||||
if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
|
||||
return hs;
|
||||
return fs;
|
||||
}
|
||||
|
||||
|
||||
/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
|
||||
static struct usb_string fsg_strings[] = {
|
||||
#ifndef FSG_NO_DEVICE_STRINGS
|
||||
{FSG_STRING_MANUFACTURER, fsg_string_manufacturer},
|
||||
{FSG_STRING_PRODUCT, fsg_string_product},
|
||||
{FSG_STRING_SERIAL, fsg_string_serial},
|
||||
{FSG_STRING_CONFIG, fsg_string_config},
|
||||
#endif
|
||||
{FSG_STRING_INTERFACE, fsg_string_interface},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings fsg_stringtab = {
|
||||
.language = 0x0409, /* en-us */
|
||||
.strings = fsg_strings,
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* If the next two routines are called while the gadget is registered,
|
||||
* the caller must own fsg->filesem for writing. */
|
||||
|
||||
static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
|
||||
{
|
||||
int ro;
|
||||
struct file *filp = NULL;
|
||||
int rc = -EINVAL;
|
||||
struct inode *inode = NULL;
|
||||
loff_t size;
|
||||
loff_t num_sectors;
|
||||
loff_t min_sectors;
|
||||
|
||||
/* R/W if we can, R/O if we must */
|
||||
ro = curlun->initially_ro;
|
||||
if (!ro) {
|
||||
filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
|
||||
if (-EROFS == PTR_ERR(filp))
|
||||
ro = 1;
|
||||
}
|
||||
if (ro)
|
||||
filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0);
|
||||
if (IS_ERR(filp)) {
|
||||
LINFO(curlun, "unable to open backing file: %s\n", filename);
|
||||
return PTR_ERR(filp);
|
||||
}
|
||||
|
||||
if (!(filp->f_mode & FMODE_WRITE))
|
||||
ro = 1;
|
||||
|
||||
if (filp->f_path.dentry)
|
||||
inode = filp->f_path.dentry->d_inode;
|
||||
if (inode && S_ISBLK(inode->i_mode)) {
|
||||
if (bdev_read_only(inode->i_bdev))
|
||||
ro = 1;
|
||||
} else if (!inode || !S_ISREG(inode->i_mode)) {
|
||||
LINFO(curlun, "invalid file type: %s\n", filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If we can't read the file, it's no good.
|
||||
* If we can't write the file, use it read-only. */
|
||||
if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) {
|
||||
LINFO(curlun, "file not readable: %s\n", filename);
|
||||
goto out;
|
||||
}
|
||||
if (!(filp->f_op->write || filp->f_op->aio_write))
|
||||
ro = 1;
|
||||
|
||||
size = i_size_read(inode->i_mapping->host);
|
||||
if (size < 0) {
|
||||
LINFO(curlun, "unable to find file size: %s\n", filename);
|
||||
rc = (int) size;
|
||||
goto out;
|
||||
}
|
||||
num_sectors = size >> 9; /* File size in 512-byte blocks */
|
||||
min_sectors = 1;
|
||||
if (curlun->cdrom) {
|
||||
num_sectors &= ~3; /* Reduce to a multiple of 2048 */
|
||||
min_sectors = 300*4; /* Smallest track is 300 frames */
|
||||
if (num_sectors >= 256*60*75*4) {
|
||||
num_sectors = (256*60*75 - 1) * 4;
|
||||
LINFO(curlun, "file too big: %s\n", filename);
|
||||
LINFO(curlun, "using only first %d blocks\n",
|
||||
(int) num_sectors);
|
||||
}
|
||||
}
|
||||
if (num_sectors < min_sectors) {
|
||||
LINFO(curlun, "file too small: %s\n", filename);
|
||||
rc = -ETOOSMALL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
get_file(filp);
|
||||
curlun->ro = ro;
|
||||
curlun->filp = filp;
|
||||
curlun->file_length = size;
|
||||
curlun->num_sectors = num_sectors;
|
||||
LDBG(curlun, "open backing file: %s\n", filename);
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
filp_close(filp, current->files);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static void fsg_lun_close(struct fsg_lun *curlun)
|
||||
{
|
||||
if (curlun->filp) {
|
||||
LDBG(curlun, "close backing file\n");
|
||||
fput(curlun->filp);
|
||||
curlun->filp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* Sync the file data, don't bother with the metadata.
|
||||
* This code was copied from fs/buffer.c:sys_fdatasync(). */
|
||||
static int fsg_lun_fsync_sub(struct fsg_lun *curlun)
|
||||
{
|
||||
struct file *filp = curlun->filp;
|
||||
|
||||
if (curlun->ro || !filp)
|
||||
return 0;
|
||||
return vfs_fsync(filp, filp->f_path.dentry, 1);
|
||||
}
|
||||
|
||||
static void store_cdrom_address(u8 *dest, int msf, u32 addr)
|
||||
{
|
||||
if (msf) {
|
||||
/* Convert to Minutes-Seconds-Frames */
|
||||
addr >>= 2; /* Convert to 2048-byte frames */
|
||||
addr += 2*75; /* Lead-in occupies 2 seconds */
|
||||
dest[3] = addr % 75; /* Frames */
|
||||
addr /= 75;
|
||||
dest[2] = addr % 60; /* Seconds */
|
||||
addr /= 60;
|
||||
dest[1] = addr; /* Minutes */
|
||||
dest[0] = 0; /* Reserved */
|
||||
} else {
|
||||
/* Absolute sector */
|
||||
put_unaligned_be32(addr, dest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct fsg_lun *curlun = fsg_lun_from_dev(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", fsg_lun_is_open(curlun)
|
||||
? curlun->ro
|
||||
: curlun->initially_ro);
|
||||
}
|
||||
|
||||
static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct fsg_lun *curlun = fsg_lun_from_dev(dev);
|
||||
struct rw_semaphore *filesem = dev_get_drvdata(dev);
|
||||
char *p;
|
||||
ssize_t rc;
|
||||
|
||||
down_read(filesem);
|
||||
if (fsg_lun_is_open(curlun)) { /* Get the complete pathname */
|
||||
p = d_path(&curlun->filp->f_path, buf, PAGE_SIZE - 1);
|
||||
if (IS_ERR(p))
|
||||
rc = PTR_ERR(p);
|
||||
else {
|
||||
rc = strlen(p);
|
||||
memmove(buf, p, rc);
|
||||
buf[rc] = '\n'; /* Add a newline */
|
||||
buf[++rc] = 0;
|
||||
}
|
||||
} else { /* No file, return 0 bytes */
|
||||
*buf = 0;
|
||||
rc = 0;
|
||||
}
|
||||
up_read(filesem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
ssize_t rc = count;
|
||||
struct fsg_lun *curlun = fsg_lun_from_dev(dev);
|
||||
struct rw_semaphore *filesem = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
if (sscanf(buf, "%d", &i) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* Allow the write-enable status to change only while the backing file
|
||||
* is closed. */
|
||||
down_read(filesem);
|
||||
if (fsg_lun_is_open(curlun)) {
|
||||
LDBG(curlun, "read-only status change prevented\n");
|
||||
rc = -EBUSY;
|
||||
} else {
|
||||
curlun->ro = !!i;
|
||||
curlun->initially_ro = !!i;
|
||||
LDBG(curlun, "read-only status set to %d\n", curlun->ro);
|
||||
}
|
||||
up_read(filesem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fsg_lun *curlun = fsg_lun_from_dev(dev);
|
||||
struct rw_semaphore *filesem = dev_get_drvdata(dev);
|
||||
int rc = 0;
|
||||
|
||||
#if 0
|
||||
if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) {
|
||||
LDBG(curlun, "eject attempt prevented\n");
|
||||
return -EBUSY; /* "Door is locked" */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Remove a trailing newline */
|
||||
if (count > 0 && buf[count-1] == '\n')
|
||||
((char *) buf)[count-1] = 0; /* Ugh! */
|
||||
|
||||
/* Eject current medium */
|
||||
down_write(filesem);
|
||||
if (fsg_lun_is_open(curlun)) {
|
||||
fsg_lun_close(curlun);
|
||||
curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
|
||||
}
|
||||
|
||||
/* Load new medium */
|
||||
if (count > 0 && buf[0]) {
|
||||
rc = fsg_lun_open(curlun, buf);
|
||||
if (rc == 0)
|
||||
curlun->unit_attention_data =
|
||||
SS_NOT_READY_TO_READY_TRANSITION;
|
||||
}
|
||||
up_write(filesem);
|
||||
return (rc < 0 ? rc : count);
|
||||
}
|
739
brick/kernel/usb_function.c
Normal file
739
brick/kernel/usb_function.c
Normal file
@ -0,0 +1,739 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This UsbFunction file is based on and inheritated from
|
||||
* the original file (f_sourcesink.c) and work done by
|
||||
* David Brownell
|
||||
*
|
||||
* >> f_sourcesink.c - USB peripheral source/sink configuration driver <<
|
||||
*
|
||||
* >> Copyright (C) 2003-2008 David Brownell <<
|
||||
* >> Copyright (C) 2008 by Nokia Corporation <<
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* HID IN/OUT Interrupt transfer FUNCTION ...
|
||||
*
|
||||
*/
|
||||
|
||||
struct f_rudolf {
|
||||
struct usb_function function;
|
||||
|
||||
struct usb_ep *in_ep;
|
||||
struct usb_ep *out_ep;
|
||||
};
|
||||
|
||||
enum // Used for signaling the IN stuff USB-state
|
||||
{ // Data from the Brick to the HOST
|
||||
USB_DATA_IDLE, //
|
||||
USB_DATA_BUSY, // Ongoing USB request
|
||||
USB_DATA_PENDING, // Data ready for X-fer, but USB busy
|
||||
USB_DATA_READY, // Initial setting
|
||||
};
|
||||
|
||||
int input_state = USB_DATA_IDLE;
|
||||
struct usb_ep *save_in_ep;
|
||||
struct usb_request *save_in_req;
|
||||
|
||||
#ifndef PCASM
|
||||
static inline struct f_rudolf *func_to_rudolf(struct usb_function *f)
|
||||
{
|
||||
return container_of(f, struct f_rudolf, function);
|
||||
}
|
||||
#else
|
||||
// Keep Eclipse happy
|
||||
#endif
|
||||
|
||||
static struct usb_interface_descriptor rudolf_intf = {
|
||||
.bLength = sizeof rudolf_intf,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 2, // Just plain in and out
|
||||
.bInterfaceClass = USB_CLASS_HID, // We go for NONE custom-driver
|
||||
.bInterfaceSubClass = 0,
|
||||
.bInterfaceProtocol = 0,
|
||||
/* .iInterface = DYNAMIC */
|
||||
};
|
||||
|
||||
static struct hid_descriptor hs_hid_rudolf_desc = {
|
||||
.bLength = sizeof hs_hid_rudolf_desc,
|
||||
.bDescriptorType = HID_DT_HID,
|
||||
.bcdHID = cpu_to_le16(0x0110),
|
||||
.bCountryCode = 0x00,
|
||||
.bNumDescriptors = 0x01, // "The one and only"
|
||||
.desc[0].bDescriptorType = 0x22, // Report Descriptor Type - 0x22 = HID
|
||||
.desc[0].wDescriptorLength = sizeof hs_hid_report_descriptor,
|
||||
/*.desc[0].bDescriptorType = DYNAMIC */
|
||||
/*.desc[0].wDescriptorLenght= DYNAMIC */
|
||||
};
|
||||
|
||||
static struct hid_descriptor fs_hid_rudolf_desc = {
|
||||
.bLength = sizeof fs_hid_rudolf_desc,
|
||||
.bDescriptorType = HID_DT_HID,
|
||||
.bcdHID = cpu_to_le16(0x0110),
|
||||
.bCountryCode = 0x00,
|
||||
.bNumDescriptors = 0x01, // "The one and only"
|
||||
.desc[0].bDescriptorType = 0x22, // Report Descriptor Type - 0x22 = HID
|
||||
.desc[0].wDescriptorLength = sizeof fs_hid_report_descriptor,
|
||||
|
||||
};
|
||||
|
||||
/* full speed support: */
|
||||
|
||||
static struct usb_endpoint_descriptor rudolf_out_fs_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = USB_DIR_OUT,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(64),
|
||||
.bInterval = 1, /* 1 = 1 mSec POLL rate for FS */
|
||||
};
|
||||
|
||||
static struct usb_endpoint_descriptor rudolf_in_fs_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = USB_DIR_IN,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(64),
|
||||
.bInterval = 1, /* 1 = 1 mSec POLL rate for FS */
|
||||
};
|
||||
|
||||
/* high speed support: */
|
||||
|
||||
static struct usb_endpoint_descriptor rudolf_in_hs_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = USB_DIR_IN,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(1024),
|
||||
.bInterval = 4, /* Calculated as :
|
||||
* 2^(value-1) * 125uS
|
||||
* i.e. value 1: 2^(1-1) * 125 uSec = 125 uSec
|
||||
* - 4: 2^(4-1) * 125 uSec = 1 mSec
|
||||
*/
|
||||
};
|
||||
|
||||
static struct usb_endpoint_descriptor rudolf_out_hs_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = USB_DIR_OUT,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(1024),
|
||||
.bInterval = 4, /* Calculated as :
|
||||
* 2^(value-1) * 125uS
|
||||
* i.e. value 1: 2^(1-1) * 125 uSec = 125 uSec
|
||||
* - 4: 2^(4-1) * 125 uSec = 1 mSec
|
||||
*/
|
||||
};
|
||||
|
||||
static struct usb_descriptor_header *hs_rudolf_descs[] = {
|
||||
(struct usb_descriptor_header *) &rudolf_intf,
|
||||
(struct usb_descriptor_header *) &hs_hid_rudolf_desc,
|
||||
(struct usb_descriptor_header *) &rudolf_in_hs_desc,
|
||||
(struct usb_descriptor_header *) &rudolf_out_hs_desc,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct usb_descriptor_header *fs_rudolf_descs[] = {
|
||||
(struct usb_descriptor_header *) &rudolf_intf,
|
||||
(struct usb_descriptor_header *) &fs_hid_rudolf_desc,
|
||||
(struct usb_descriptor_header *) &rudolf_in_fs_desc,
|
||||
(struct usb_descriptor_header *) &rudolf_out_fs_desc,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* function-specific strings: */
|
||||
|
||||
static struct usb_string strings_rudolf[] = {
|
||||
[0].s = "Xfer data to and from EV3 brick",
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings stringtab_rudolf = {
|
||||
.language = 0x0409, /* en-us */
|
||||
.strings = strings_rudolf,
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings *rudolf_strings[] = {
|
||||
&stringtab_rudolf,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
f_rudolf_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
{
|
||||
struct usb_composite_dev *cdev = c->cdev;
|
||||
struct f_rudolf *rudolf = func_to_rudolf(f);
|
||||
int id;
|
||||
|
||||
/* allocate interface ID(s) */
|
||||
id = usb_interface_id(c, f);
|
||||
if (id < 0)
|
||||
return id;
|
||||
rudolf_intf.bInterfaceNumber = id;
|
||||
|
||||
/* allocate endpoints */
|
||||
rudolf->in_ep = usb_ep_autoconfig(cdev->gadget, &rudolf_in_fs_desc);
|
||||
if (!rudolf->in_ep) {
|
||||
autoconf_fail:
|
||||
ERROR(cdev, "%s: can't autoconfigure on %s\n",
|
||||
f->name, cdev->gadget->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
rudolf->in_ep->driver_data = cdev; /* claim */
|
||||
|
||||
rudolf->out_ep = usb_ep_autoconfig(cdev->gadget, &rudolf_out_fs_desc);
|
||||
if (!rudolf->out_ep)
|
||||
goto autoconf_fail;
|
||||
rudolf->out_ep->driver_data = cdev; /* claim */
|
||||
|
||||
|
||||
/* support high speed hardware */
|
||||
if (gadget_is_dualspeed(c->cdev->gadget)) {
|
||||
|
||||
rudolf_in_hs_desc.bEndpointAddress =
|
||||
rudolf_in_fs_desc.bEndpointAddress;
|
||||
rudolf_out_hs_desc.bEndpointAddress =
|
||||
rudolf_out_fs_desc.bEndpointAddress;
|
||||
f->hs_descriptors = hs_rudolf_descs;
|
||||
f->descriptors = fs_rudolf_descs;
|
||||
}
|
||||
|
||||
DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
|
||||
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
|
||||
f->name, rudolf->in_ep->name, rudolf->out_ep->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
f_rudolf_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||
{
|
||||
kfree(func_to_rudolf(f));
|
||||
}
|
||||
|
||||
static void usb_req_arm(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (UsbSpeed.Speed == FULL_SPEED)
|
||||
{
|
||||
req->length = 64;
|
||||
req->actual = 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
req->length = 1024;
|
||||
req->actual = 1024;
|
||||
}
|
||||
|
||||
status = usb_ep_queue(ep, req, GFP_ATOMIC);
|
||||
if (status) {
|
||||
usb_ep_set_halt(ep);
|
||||
/* FIXME recover later ... somehow */
|
||||
}
|
||||
}
|
||||
|
||||
static int read_data_from_host(struct usb_request *req)
|
||||
{
|
||||
unsigned i;
|
||||
u8 *buf = req->buf;
|
||||
|
||||
int from_host_length = 0; // NO ACCESS LOCKS YET
|
||||
|
||||
// test for actual length > 0
|
||||
|
||||
for (i = 0; i < req->actual; i++, buf++)
|
||||
{
|
||||
|
||||
usb_char_buffer_out[i] = *buf;
|
||||
from_host_length++;
|
||||
}
|
||||
|
||||
return (from_host_length);
|
||||
}
|
||||
|
||||
static void write_data_to_the_host(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
unsigned i;
|
||||
u8 *buf = req->buf;
|
||||
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("WR to HOST req->length = %d\r\n", req->length);
|
||||
#endif
|
||||
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("USB = %d, %d\r\n", usb_char_buffer_in[2], usb_char_buffer_in[3]);
|
||||
#endif
|
||||
#undef DEBUG
|
||||
|
||||
for (i = 0; i < req->length; i++)
|
||||
*buf++ = usb_char_buffer_in[i];
|
||||
usb_char_in_length = 0; // Reset and ready
|
||||
}
|
||||
|
||||
static void rudolf_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
struct f_rudolf *rudolf = ep->driver_data;
|
||||
int status = req->status;
|
||||
|
||||
|
||||
switch ( status ) {
|
||||
|
||||
case 0: /* normal completion? */
|
||||
if (ep == rudolf->out_ep) // An OUT completion?
|
||||
{
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("Rudolf_complete OUT\n");
|
||||
#endif
|
||||
|
||||
usb_char_out_length = read_data_from_host(req);
|
||||
usb_req_arm(ep, req);
|
||||
}
|
||||
else // We have an INPUT request complete
|
||||
{
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("Rudolf_complete IN\n");
|
||||
#endif
|
||||
|
||||
switch(input_state) // State of Brick data x-fer
|
||||
{
|
||||
case USB_DATA_READY: //should be BUSY or PENDING....
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("IN_IN_IN - READY ?????\n");
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
case USB_DATA_PENDING: //
|
||||
// #define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("IN_IN_IN - PENDING settes to BUSY\n");
|
||||
#endif
|
||||
|
||||
input_state = USB_DATA_BUSY;
|
||||
write_data_to_the_host(ep, req);
|
||||
usb_req_arm(ep, req); // new request
|
||||
break;
|
||||
|
||||
case USB_DATA_BUSY: //
|
||||
#ifdef DEBUG
|
||||
printk("IN_IN_IN - BUSY settes to READY\n");
|
||||
#endif
|
||||
#undef DEBUG
|
||||
input_state = USB_DATA_READY;
|
||||
// and relax
|
||||
break;
|
||||
|
||||
case USB_DATA_IDLE: // too lazy
|
||||
#ifdef DEBUG
|
||||
printk("IN_IN_IN - IDLE\n");
|
||||
#endif
|
||||
//#undef DEBUG
|
||||
|
||||
break;
|
||||
|
||||
default: break; // hmmm.
|
||||
}
|
||||
// Reset the buffer size - Ready again
|
||||
usb_char_in_length = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
/* this endpoint is normally active while we're configured */
|
||||
|
||||
case -ESHUTDOWN: /* disconnect from host */
|
||||
// REMOVED 26102012 (*pUsbSpeed).Speed = FULL_SPEED;
|
||||
case -ECONNABORTED: /* hardware forced ep reset */
|
||||
case -ECONNRESET: /* request dequeued */
|
||||
//case -ESHUTDOWN: /* disconnect from host */
|
||||
if (ep == rudolf->out_ep)
|
||||
read_data_from_host(req);
|
||||
free_ep_req(ep, req);
|
||||
return;
|
||||
|
||||
case -EOVERFLOW: /* buffer overrun on read means that
|
||||
we didn't provide a big enough
|
||||
buffer.
|
||||
*/
|
||||
default:
|
||||
//#if 1
|
||||
// DBG(cdev, "%s complete --> %d, %d/%d\n", ep->name,
|
||||
// status, req->actual, req->length);
|
||||
//#endif
|
||||
case -EREMOTEIO: /* short read */
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int rudolf_start_ep(struct f_rudolf *rudolf, bool is_in)
|
||||
{
|
||||
struct usb_ep *ep;
|
||||
struct usb_request *req;
|
||||
int status;
|
||||
|
||||
ep = is_in ? rudolf->in_ep : rudolf->out_ep;
|
||||
req = alloc_ep_req(ep);
|
||||
if (!req)
|
||||
return -ENOMEM;
|
||||
|
||||
req->complete = rudolf_complete;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("UsbSpeed.Speed = %d\n\r", UsbSpeed.Speed);
|
||||
#endif
|
||||
|
||||
if (UsbSpeed.Speed == FULL_SPEED)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printk("rudolf_start_ep FULL\n\r");
|
||||
#endif
|
||||
|
||||
(*pUsbSpeed).Speed = FULL_SPEED;
|
||||
req->length = 64; // Full speed max buffer size
|
||||
req->actual = 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printk("rudolf_start_ep HIGH\n\r");
|
||||
#endif
|
||||
|
||||
(*pUsbSpeed).Speed = HIGH_SPEED;
|
||||
req->length = 1024; // High speed max buffer size
|
||||
req->actual = 1024;
|
||||
}
|
||||
|
||||
if (is_in)
|
||||
{
|
||||
save_in_ep = ep;
|
||||
save_in_req = req;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("req->length = %d ***** Rudolf_Start_Ep_in\n\r", req->length);
|
||||
#endif
|
||||
|
||||
// reinit_write_data(ep, req);
|
||||
input_state = USB_DATA_BUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printk("***** Rudolf_Start_Ep_out\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
status = usb_ep_queue(ep, req, GFP_ATOMIC);
|
||||
|
||||
if (status) {
|
||||
struct usb_composite_dev *cdev;
|
||||
|
||||
cdev = rudolf->function.config->cdev;
|
||||
ERROR(cdev, "start %s %s --> %d\n",
|
||||
is_in ? "IN" : "OUT",
|
||||
ep->name, status);
|
||||
|
||||
free_ep_req(ep, req);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void disable_rudolf(struct f_rudolf *rudolf)
|
||||
{
|
||||
struct usb_composite_dev *cdev;
|
||||
|
||||
cdev = rudolf->function.config->cdev;
|
||||
disable_endpoints(cdev, rudolf->in_ep, rudolf->out_ep);
|
||||
VDBG(cdev, "%s disabled\n", rudolf->function.name);
|
||||
}
|
||||
|
||||
static int
|
||||
enable_rudolf(struct usb_composite_dev *cdev, struct f_rudolf *rudolf)
|
||||
{
|
||||
int result = 0;
|
||||
const struct usb_endpoint_descriptor *ep_in, *ep_out;
|
||||
struct usb_ep *ep;
|
||||
|
||||
ep_in = ep_choose(cdev->gadget, &rudolf_in_hs_desc, &rudolf_in_fs_desc);
|
||||
|
||||
ep_out = ep_choose(cdev->gadget, &rudolf_out_hs_desc, &rudolf_out_fs_desc);
|
||||
|
||||
ep = rudolf->in_ep;
|
||||
|
||||
result = usb_ep_enable(ep, ep_in);
|
||||
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
ep->driver_data = rudolf;
|
||||
|
||||
result = rudolf_start_ep(rudolf, true);
|
||||
|
||||
if (result < 0) {
|
||||
fail:
|
||||
ep = rudolf->in_ep;
|
||||
usb_ep_disable(ep);
|
||||
ep->driver_data = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* one endpoint reads (sinks) anything OUT (from the host) */
|
||||
ep = rudolf->out_ep;
|
||||
result = usb_ep_enable(ep, ep_out);
|
||||
|
||||
if (result < 0)
|
||||
goto fail;
|
||||
|
||||
ep->driver_data = rudolf;
|
||||
|
||||
result = rudolf_start_ep(rudolf, false);
|
||||
|
||||
if (result < 0) {
|
||||
usb_ep_disable(ep);
|
||||
ep->driver_data = NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
DBG(cdev, "%s enabled\n", rudolf->function.name);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int f_rudolf_set_alt(struct usb_function *f,
|
||||
unsigned intf, unsigned alt)
|
||||
{
|
||||
struct f_rudolf *rudolf = func_to_rudolf(f);
|
||||
struct usb_composite_dev *cdev = f->config->cdev;
|
||||
|
||||
/* we know alt is zero */
|
||||
if (rudolf->in_ep->driver_data)
|
||||
disable_rudolf(rudolf);
|
||||
|
||||
return enable_rudolf(cdev, rudolf);
|
||||
}
|
||||
|
||||
static void f_rudolf_disable(struct usb_function *f)
|
||||
{
|
||||
struct f_rudolf *rudolf = func_to_rudolf(f);
|
||||
|
||||
disable_rudolf(rudolf);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int msg_config(struct usb_configuration *c);
|
||||
|
||||
static int rudolf_bind_config(struct usb_configuration *c)
|
||||
{
|
||||
struct f_rudolf *rudolf;
|
||||
int status;
|
||||
|
||||
rudolf = kzalloc(sizeof *rudolf, GFP_KERNEL);
|
||||
if (!rudolf)
|
||||
return -ENOMEM;
|
||||
|
||||
rudolf->function.name = "rudolf xfer";
|
||||
rudolf->function.descriptors = hs_rudolf_descs;
|
||||
rudolf->function.bind = f_rudolf_bind;
|
||||
rudolf->function.unbind = f_rudolf_unbind;
|
||||
rudolf->function.set_alt = f_rudolf_set_alt;
|
||||
rudolf->function.disable = f_rudolf_disable;
|
||||
|
||||
status = usb_add_function(c, &rudolf->function);
|
||||
if (status) {
|
||||
kfree(rudolf);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
status = msg_config(c);
|
||||
if (status) {
|
||||
kfree(rudolf);
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifndef PCASM
|
||||
static int rudolf_setup(struct usb_configuration *c,
|
||||
const struct usb_ctrlrequest *ctrl)
|
||||
{
|
||||
struct usb_request *req = c->cdev->req;
|
||||
int value = -EOPNOTSUPP;
|
||||
u16 w_index = le16_to_cpu(ctrl->wIndex);
|
||||
u16 w_value = le16_to_cpu(ctrl->wValue);
|
||||
u16 w_length = le16_to_cpu(ctrl->wLength);
|
||||
u16 length = 0;
|
||||
|
||||
/* composite driver infrastructure handles everything except
|
||||
* the two control test requests.
|
||||
*/
|
||||
|
||||
switch (ctrl->bRequest) {
|
||||
|
||||
/*
|
||||
* These are the same vendor-specific requests supported by
|
||||
* Intel's USB 2.0 compliance test devices. We exceed that
|
||||
* device spec by allowing multiple-packet requests.
|
||||
*
|
||||
* NOTE: the Control-OUT data stays in req->buf ... better
|
||||
* would be copying it into a scratch buffer, so that other
|
||||
* requests may safely intervene.
|
||||
*/
|
||||
|
||||
case 0x5b: /* control WRITE test -- fill the buffer */
|
||||
if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
|
||||
goto unknown;
|
||||
if (w_value || w_index)
|
||||
break;
|
||||
/* just read that many bytes into the buffer */
|
||||
if (w_length > req->length)
|
||||
break;
|
||||
value = w_length;
|
||||
break;
|
||||
case 0x5c: /* control READ test -- return the buffer */
|
||||
if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
|
||||
goto unknown;
|
||||
if (w_value || w_index)
|
||||
break;
|
||||
/* expect those bytes are still in the buffer; send back */
|
||||
if (w_length > req->length)
|
||||
break;
|
||||
value = w_length;
|
||||
break;
|
||||
|
||||
default:
|
||||
unknown:
|
||||
VDBG(c->cdev,
|
||||
"unknown control req%02x.%02x v%04x i%04x l%d\n",
|
||||
ctrl->bRequestType, ctrl->bRequest,
|
||||
w_value, w_index, w_length);
|
||||
}
|
||||
|
||||
//HER SKAL HID DESC SENDES!!!
|
||||
switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
|
||||
|
||||
|
||||
case ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8
|
||||
| USB_REQ_GET_DESCRIPTOR):
|
||||
switch (w_value >> 8) {
|
||||
case HID_DT_REPORT:
|
||||
//VDBG(cdev, "USB_REQ_GET_DESCRIPTOR: REPORT\n");
|
||||
length = w_length;
|
||||
length = min_t(unsigned short, length,
|
||||
sizeof hs_hid_report_descriptor);
|
||||
memcpy(req->buf, hs_hid_report_descriptor, length);
|
||||
value = length;
|
||||
goto respond;
|
||||
break;
|
||||
|
||||
default:
|
||||
//VDBG(cdev, "Unknown decriptor request 0x%x\n",
|
||||
// value >> 8);
|
||||
goto stall;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//VDBG(cdev, "Unknown request 0x%x\n",
|
||||
// ctrl->bRequest);
|
||||
goto stall;
|
||||
break;
|
||||
}
|
||||
|
||||
//HERTIL
|
||||
/* respond with data transfer or status phase? */
|
||||
stall:
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
respond:
|
||||
if (value >= 0) {
|
||||
VDBG(c->cdev, "source/sink req%02x.%02x v%04x i%04x l%d\n",
|
||||
ctrl->bRequestType, ctrl->bRequest,
|
||||
w_value, w_index, w_length);
|
||||
req->zero = 0;
|
||||
req->length = value;
|
||||
value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC);
|
||||
if (value < 0)
|
||||
ERROR(c->cdev, "source/sinkc response, err %d\n",
|
||||
value);
|
||||
}
|
||||
|
||||
/* device either stalls (value < 0) or reports success */
|
||||
return value;
|
||||
}
|
||||
#else
|
||||
// Keep Eclipse happy
|
||||
#endif
|
||||
|
||||
static struct usb_configuration rudolf_driver = {
|
||||
.label = "rudolf driver",
|
||||
.strings = rudolf_strings,
|
||||
.bind = rudolf_bind_config,
|
||||
.setup = rudolf_setup,
|
||||
.bConfigurationValue = 1,
|
||||
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
|
||||
/* .iConfiguration = DYNAMIC */
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
int rudolf_add(struct usb_composite_dev *cdev, bool autoresume)
|
||||
{
|
||||
int id;
|
||||
|
||||
/* allocate string ID(s) */
|
||||
id = usb_string_id(cdev);
|
||||
if (id < 0)
|
||||
return id;
|
||||
strings_rudolf[0].id = id;
|
||||
|
||||
rudolf_intf.iInterface = id;
|
||||
rudolf_driver.iConfiguration = 1; // id;
|
||||
|
||||
/* support autoresume for remote wakeup testing */
|
||||
if (autoresume)
|
||||
rudolf_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
|
||||
|
||||
/* support OTG systems */
|
||||
if (gadget_is_otg(cdev->gadget)) {
|
||||
rudolf_driver.descriptors = otg_desc;
|
||||
rudolf_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
|
||||
}
|
||||
|
||||
|
||||
return usb_add_config(cdev, &rudolf_driver);
|
||||
}
|
Loading…
Reference in New Issue
Block a user