Index: apps/debug_menu.c =================================================================== --- apps/debug_menu.c (revision 20720) +++ apps/debug_menu.c (working copy) @@ -191,7 +191,7 @@ int selpos = gui_synclist_get_sel_pos(lists); #if NUM_CORES > 1 if (selpos >= NUM_CORES) - remove_thread(&threads[selpos - NUM_CORES]); + remove_thread(threads[selpos - NUM_CORES].id); #else remove_thread(&threads[selpos]); #endif @@ -683,7 +683,7 @@ lcd_update(); while (!(action_userabort(TIMEOUT_BLOCK))); - + #else /* Define this function in your target tree */ return __dbg_hw_info(); @@ -1757,7 +1757,7 @@ /* Conversion disabled */ snprintf(buf, 30, "T Battery: ?"); } - + lcd_puts(0, line++, buf); #elif defined(SANSA_E200) || defined(SANSA_C200) || defined(SANSA_CLIP) const int first = CHARGE_STATE_DISABLED; @@ -1782,7 +1782,7 @@ str ? str : ""); lcd_puts(0, 4, buf); - snprintf(buf, sizeof(buf), "CHARGER: %02X", + snprintf(buf, sizeof(buf), "CHARGER: %02X", ascodec_read(AS3514_CHARGER)); lcd_puts(0, 5, buf); #else @@ -1962,7 +1962,7 @@ } return btn; } -#elif (CONFIG_STORAGE & STORAGE_ATA) +#elif (CONFIG_STORAGE & STORAGE_ATA) static int disk_callback(int btn, struct gui_synclist *lists) { (void)lists; @@ -2116,7 +2116,7 @@ } #endif -#if (CONFIG_STORAGE & STORAGE_ATA) +#if (CONFIG_STORAGE & STORAGE_ATA) static bool dbg_identify_info(void) { int fd = creat("/identify_info.bin"); @@ -2210,9 +2210,9 @@ simplelist_addline(SIMPLELIST_ADD_LINE, "Commit delayed: %s", stat->commit_delayed ? "Yes" : "No"); - simplelist_addline(SIMPLELIST_ADD_LINE, "Queue length: %d", + simplelist_addline(SIMPLELIST_ADD_LINE, "Queue length: %d", stat->queue_length); - + if (synced) { synced = false; @@ -2237,7 +2237,7 @@ info.action_callback = database_callback; info.hide_selection = true; info.scroll_all = true; - + /* Don't do nonblock here, must give enough processing time for tagcache thread. */ /* info.timeout = TIMEOUT_NOBLOCK; */ @@ -2583,17 +2583,38 @@ } #endif -#if defined(HAVE_USBSTACK) && defined(ROCKBOX_HAS_LOGF) && defined(USB_SERIAL) -static bool logf_usb_serial(void) +#if defined (HAVE_USBSTACK) +static bool toggle_usb_core_driver(int driver, char *msg) { - bool serial_enabled = !usb_core_driver_enabled(USB_DRIVER_SERIAL); - usb_core_enable_driver(USB_DRIVER_SERIAL,serial_enabled); - splashf(HZ, "USB logf %s", - serial_enabled?"enabled":"disabled"); + bool enabled = !usb_core_driver_enabled(driver); + + usb_core_enable_driver(driver,enabled); + splashf(HZ, "%s %s", msg, enabled?"enabled":"disabled"); + return false; } +#if 0 && defined(USB_STORAGE) +static bool toggle_usb_mass_storage(void) +{ + return toggle_usb_core_driver(USB_DRIVER_MASS_STORAGE,"USB Mass Storage"); +} #endif +#if defined(ROCKBOX_HAS_LOGF) && defined(USB_SERIAL) +static bool toggle_usb_serial(void) +{ + return toggle_usb_core_driver(USB_DRIVER_SERIAL,"USB Serial"); +} +#endif + +#if defined(USB_HID) +static bool toggle_usb_hid(void) +{ + return toggle_usb_core_driver(USB_DRIVER_HID, "USB HID"); +} +#endif +#endif + #if CONFIG_USBOTG == USBOTG_ISP1583 extern int dbg_usb_num_items(void); extern char* dbg_usb_item(int selected_item, void *data, char *buffer, size_t buffer_len); @@ -2611,7 +2632,7 @@ struct simplelist_info isp1583; isp1583.scroll_all = true; simplelist_info_init(&isp1583, "ISP1583", dbg_usb_num_items(), NULL); - isp1583.timeout = HZ/100; + isp1583.timeout = HZ/100; isp1583.hide_selection = true; isp1583.get_name = dbg_usb_item; isp1583.action_callback = isp1583_action_callback; @@ -2636,7 +2657,7 @@ struct simplelist_info pic; pic.scroll_all = true; simplelist_info_init(&pic, "PIC", pic_dbg_num_items(), NULL); - pic.timeout = HZ/100; + pic.timeout = HZ/100; pic.hide_selection = true; pic.get_name = pic_dbg_item; pic.action_callback = pic_action_callback; @@ -2728,14 +2749,19 @@ {"logf", logfdisplay }, {"logfdump", logfdump }, #endif -#if defined(HAVE_USBSTACK) && defined(ROCKBOX_HAS_LOGF) && defined(USB_SERIAL) - {"logf over usb",logf_usb_serial }, +#if defined(HAVE_USBSTACK) +#if 0 && defined(USB_STORAGE) + {"USB Mass-Storage driver", toggle_usb_mass_storage }, #endif -#if 0 && defined(HAVE_USBSTACK) && defined(USB_STORAGE) - {"reconnect usb storage",usb_reconnect}, +#if defined(ROCKBOX_HAS_LOGF) && defined(USB_SERIAL) + {"USB serial driver (logf)", toggle_usb_serial }, #endif +#if defined(USB_HID) + {"USB HID driver", toggle_usb_hid }, +#endif +#endif /* HAVE_USBSTACK */ #ifdef CPU_BOOST_LOGGING - {"cpu_boost log",cpu_boost_log}, + {"cpu_boost log", cpu_boost_log}, #endif #if (defined(HAVE_WHEEL_ACCELERATION) && (CONFIG_KEYPAD==IPOD_4G_PAD) && !defined(SIMULATOR)) {"Debug scrollwheel", dbg_scrollwheel}, Index: firmware/export/usb_ch9.h =================================================================== --- firmware/export/usb_ch9.h (revision 20720) +++ firmware/export/usb_ch9.h (working copy) @@ -27,8 +27,13 @@ * This file holds USB constants and structures that are needed for * USB device APIs. These are used by the USB device model, which is * defined in chapter 9 of the USB 2.0 specification and in the - * Wireless USB 1.0 (spread around). + * Wireless USB 1.0 (spread around). Linux has several APIs in C that + * need these: * + * - the master/host side Linux-USB kernel driver API; + * - the "usbfs" user space API; and + * - the Linux "gadget" slave/device/peripheral side driver API. + * * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems * act either as a USB master/host or as a USB slave/device. That means * the master and slave side APIs benefit from working well together. @@ -55,34 +60,55 @@ #include +/*-------------------------------------------------------------------------*/ + +/* CONTROL REQUEST SUPPORT */ + /* * USB directions * * This bit flag is used in endpoint descriptors' bEndpointAddress field. * It's also one of three fields in control requests bRequestType. */ -#define USB_DIR_OUT 0 /* to device */ -#define USB_DIR_IN 0x80 /* to host */ +#define USB_DIR_OUT 0 /* to device */ +#define USB_DIR_IN 0x80 /* to host */ /* * USB types, the second of three bRequestType fields */ -#define USB_TYPE_MASK (0x03 << 5) -#define USB_TYPE_STANDARD (0x00 << 5) -#define USB_TYPE_CLASS (0x01 << 5) -#define USB_TYPE_VENDOR (0x02 << 5) -#define USB_TYPE_RESERVED (0x03 << 5) +#define USB_TYPE_MASK (0x03 << 5) +#define USB_TYPE_STANDARD (0x00 << 5) +#define USB_TYPE_CLASS (0x01 << 5) +#define USB_TYPE_VENDOR (0x02 << 5) +#define USB_TYPE_RESERVED (0x03 << 5) /* * USB recipients, the third of three bRequestType fields */ -#define USB_RECIP_MASK 0x1f -#define USB_RECIP_DEVICE 0x00 -#define USB_RECIP_INTERFACE 0x01 -#define USB_RECIP_ENDPOINT 0x02 -#define USB_RECIP_OTHER 0x03 +#define USB_RECIP_MASK 0x1f +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 -/*-------------------------------------------------------------------------*/ +/* + * Standard requests, for the bRequest field of a SETUP packet. + * + * These are qualified by the bRequestType field, so that for example + * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved + * by a GET_STATUS request. + */ +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C /** * struct usb_ctrlrequest - SETUP data for a USB device control request @@ -91,34 +117,24 @@ * @wValue: matches the USB wValue field (le16 byte order) * @wIndex: matches the USB wIndex field (le16 byte order) * @wLength: matches the USB wLength field (le16 byte order) + * + * This structure is used to send control requests to a USB device. It matches + * the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the + * USB spec for a fuller description of the different fields, and what they are + * used for. + * + * Note that the driver for any interface can issue control requests. + * For most devices, interfaces don't coordinate with each other, so + * such requests may be made at any time. */ struct usb_ctrlrequest { - uint8_t bRequestType; - uint8_t bRequest; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; + uint8_t bRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; } __attribute__ ((packed)); -/* - * Standard requests, for the bRequest field of a SETUP packet. - * - * These are qualified by the bRequestType field, so that for example - * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved - * by a GET_STATUS request. - */ -#define USB_REQ_GET_STATUS 0x00 -#define USB_REQ_CLEAR_FEATURE 0x01 -#define USB_REQ_SET_FEATURE 0x03 -#define USB_REQ_SET_ADDRESS 0x05 -#define USB_REQ_GET_DESCRIPTOR 0x06 -#define USB_REQ_SET_DESCRIPTOR 0x07 -#define USB_REQ_GET_CONFIGURATION 0x08 -#define USB_REQ_SET_CONFIGURATION 0x09 -#define USB_REQ_GET_INTERFACE 0x0A -#define USB_REQ_SET_INTERFACE 0x0B -#define USB_REQ_SYNCH_FRAME 0x0C - /*-------------------------------------------------------------------------*/ /* @@ -138,9 +154,10 @@ #define USB_DT_STRING 0x03 #define USB_DT_INTERFACE 0x04 #define USB_DT_ENDPOINT 0x05 -#define USB_DT_DEVICE_QUALIFIER 0x06 -#define USB_DT_OTHER_SPEED_CONFIG 0x07 -#define USB_DT_INTERFACE_POWER 0x08 +#define USB_DT_DEVICE_QUALIFIER 0x06 +#define USB_DT_OTHER_SPEED_CONFIG 0x07 +#define USB_DT_INTERFACE_POWER 0x08 + /* these are from a minor usb 2.0 revision (ECN) */ #define USB_DT_OTG 0x09 #define USB_DT_DEBUG 0x0a @@ -154,61 +171,71 @@ #define USB_DT_WIRELESS_ENDPOINT_COMP 0x11 #define USB_DT_WIRE_ADAPTER 0x21 #define USB_DT_RPIPE 0x22 +#define USB_DT_CS_RADIO_CONTROL 0x23 /* Conventional codes for class-specific descriptors. The convention is * defined in the USB "Common Class" Spec (3.11). Individual class specs * are authoritative for their usage, not the "common class" writeup. */ -#define USB_DT_CS_DEVICE (USB_TYPE_CLASS | USB_DT_DEVICE) -#define USB_DT_CS_CONFIG (USB_TYPE_CLASS | USB_DT_CONFIG) -#define USB_DT_CS_STRING (USB_TYPE_CLASS | USB_DT_STRING) -#define USB_DT_CS_INTERFACE (USB_TYPE_CLASS | USB_DT_INTERFACE) -#define USB_DT_CS_ENDPOINT (USB_TYPE_CLASS | USB_DT_ENDPOINT) +#define USB_DT_CS_DEVICE (USB_TYPE_CLASS | USB_DT_DEVICE) +#define USB_DT_CS_CONFIG (USB_TYPE_CLASS | USB_DT_CONFIG) +#define USB_DT_CS_STRING (USB_TYPE_CLASS | USB_DT_STRING) +#define USB_DT_CS_INTERFACE (USB_TYPE_CLASS | USB_DT_INTERFACE) +#define USB_DT_CS_ENDPOINT (USB_TYPE_CLASS | USB_DT_ENDPOINT) +/* All standard descriptors have these 2 fields at the beginning */ +struct usb_descriptor_header { + uint8_t bLength; + uint8_t bDescriptorType; +} __attribute__ ((packed)); + + /*-------------------------------------------------------------------------*/ /* USB_DT_DEVICE: Device descriptor */ struct usb_device_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdUSB; - uint8_t bDeviceClass; - uint8_t bDeviceSubClass; - uint8_t bDeviceProtocol; - uint8_t bMaxPacketSize0; - uint16_t idVendor; - uint16_t idProduct; - uint16_t bcdDevice; - uint8_t iManufacturer; - uint8_t iProduct; - uint8_t iSerialNumber; - uint8_t bNumConfigurations; + uint8_t bLength; + uint8_t bDescriptorType; + + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; } __attribute__ ((packed)); -#define USB_DT_DEVICE_SIZE 18 +#define USB_DT_DEVICE_SIZE 18 + /* * Device and/or Interface Class codes * as found in bDeviceClass or bInterfaceClass * and defined by www.usb.org documents */ -#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ -#define USB_CLASS_AUDIO 1 -#define USB_CLASS_COMM 2 -#define USB_CLASS_HID 3 -#define USB_CLASS_PHYSICAL 5 -#define USB_CLASS_STILL_IMAGE 6 -#define USB_CLASS_PRINTER 7 -#define USB_CLASS_MASS_STORAGE 8 -#define USB_CLASS_HUB 9 -#define USB_CLASS_CDC_DATA 0x0a -#define USB_CLASS_CSCID 0x0b /* chip+ smart card */ -#define USB_CLASS_CONTENT_SEC 0x0d /* content security */ -#define USB_CLASS_VIDEO 0x0e -#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 -#define USB_CLASS_MISC 0xef -#define USB_CLASS_APP_SPEC 0xfe -#define USB_CLASS_VENDOR_SPEC 0xff +#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_COMM 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_PHYSICAL 5 +#define USB_CLASS_STILL_IMAGE 6 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_CDC_DATA 0x0a +#define USB_CLASS_CSCID 0x0b /* chip+ smart card */ +#define USB_CLASS_CONTENT_SEC 0x0d /* content security */ +#define USB_CLASS_VIDEO 0x0e +#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 +#define USB_CLASS_MISC 0xef +#define USB_CLASS_APP_SPEC 0xfe +#define USB_CLASS_VENDOR_SPEC 0xff /*-------------------------------------------------------------------------*/ @@ -221,32 +248,33 @@ * descriptors. */ struct usb_config_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wTotalLength; - uint8_t bNumInterfaces; - uint8_t bConfigurationValue; - uint8_t iConfiguration; - uint8_t bmAttributes; - uint8_t bMaxPower; + uint8_t bLength; + uint8_t bDescriptorType; + + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; } __attribute__ ((packed)); -#define USB_DT_CONFIG_SIZE 9 +#define USB_DT_CONFIG_SIZE 9 /* from config descriptor bmAttributes */ -#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */ -#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */ -#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */ -#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */ +#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */ +#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */ +#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */ +#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */ /*-------------------------------------------------------------------------*/ /* USB_DT_STRING: String descriptor */ struct usb_string_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; + uint8_t bLength; + uint8_t bDescriptorType; - uint16_t wString[]; /* UTF-16LE encoded */ + uint16_t wString[]; /* UTF-16LE encoded */ } __attribute__ ((packed)); /* note that "string" zero is special, it holds language codes that @@ -257,130 +285,129 @@ /* USB_DT_INTERFACE: Interface descriptor */ struct usb_interface_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; + uint8_t bLength; + uint8_t bDescriptorType; - uint8_t bInterfaceNumber; - uint8_t bAlternateSetting; - uint8_t bNumEndpoints; - uint8_t bInterfaceClass; - uint8_t bInterfaceSubClass; - uint8_t bInterfaceProtocol; - uint8_t iInterface; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; } __attribute__ ((packed)); -#define USB_DT_INTERFACE_SIZE 9 +#define USB_DT_INTERFACE_SIZE 9 /*-------------------------------------------------------------------------*/ /* USB_DT_ENDPOINT: Endpoint descriptor */ struct usb_endpoint_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; + uint8_t bLength; + uint8_t bDescriptorType; - uint8_t bEndpointAddress; - uint8_t bmAttributes; - uint16_t wMaxPacketSize; - uint8_t bInterval; - - /* NOTE: these two are _only_ in audio endpoints. */ - /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */ - //uint8_t bRefresh; - //uint8_t bSynchAddress; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; } __attribute__ ((packed)); -#define USB_DT_ENDPOINT_SIZE 7 -#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ +#define USB_DT_ENDPOINT_SIZE 7 +#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ + +/* + * Endpoints + */ +#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ +#define USB_ENDPOINT_DIR_MASK 0x80 + +#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ +#define USB_ENDPOINT_XFER_CONTROL 0 +#define USB_ENDPOINT_XFER_ISOC 1 +#define USB_ENDPOINT_XFER_BULK 2 +#define USB_ENDPOINT_XFER_INT 3 +#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 + + /*-------------------------------------------------------------------------*/ /* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */ struct usb_qualifier_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; + uint8_t bLength; + uint8_t bDescriptorType; - uint16_t bcdUSB; - uint8_t bDeviceClass; - uint8_t bDeviceSubClass; - uint8_t bDeviceProtocol; - uint8_t bMaxPacketSize0; - uint8_t bNumConfigurations; - uint8_t bRESERVED; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint8_t bNumConfigurations; + uint8_t bRESERVED; } __attribute__ ((packed)); + /*-------------------------------------------------------------------------*/ /* USB_DT_OTG (from OTG 1.0a supplement) */ struct usb_otg_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; + uint8_t bLength; + uint8_t bDescriptorType; - uint8_t bmAttributes; /* support for HNP, SRP, etc */ + uint8_t bmAttributes; /* support for HNP, SRP, etc */ } __attribute__ ((packed)); /* from usb_otg_descriptor.bmAttributes */ -#define USB_OTG_SRP (1 << 0) -#define USB_OTG_HNP (1 << 1) /* swap host/device roles */ +#define USB_OTG_SRP (1 << 0) +#define USB_OTG_HNP (1 << 1) /* swap host/device roles */ /*-------------------------------------------------------------------------*/ /* USB_DT_DEBUG: for special highspeed devices, replacing serial console */ struct usb_debug_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; + uint8_t bLength; + uint8_t bDescriptorType; - /* bulk endpoints with 8 byte maxpacket */ - uint8_t bDebugInEndpoint; - uint8_t bDebugOutEndpoint; -}; + /* bulk endpoints with 8 byte maxpacket */ + uint8_t bDebugInEndpoint; + uint8_t bDebugOutEndpoint; +} __attribute__((packed)); /*-------------------------------------------------------------------------*/ +/* USB 2.0 defines three speeds, here's how Linux identifies them */ -/* - * Endpoints - */ -#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ -#define USB_ENDPOINT_XFER_CONTROL 0 -#define USB_ENDPOINT_XFER_ISOC 1 -#define USB_ENDPOINT_XFER_BULK 2 -#define USB_ENDPOINT_XFER_INT 3 - enum usb_device_speed { - USB_SPEED_UNKNOWN = 0, /* enumerating */ - USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ - USB_SPEED_HIGH, /* usb 2.0 */ - USB_SPEED_VARIABLE, /* wireless (usb 2.5) */ + USB_SPEED_UNKNOWN = 0, /* enumerating */ + USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ + USB_SPEED_HIGH, /* usb 2.0 */ + USB_SPEED_VARIABLE, /* wireless (usb 2.5) */ }; enum usb_device_state { - /* NOTATTACHED isn't in the USB spec, and this state acts - * the same as ATTACHED ... but it's clearer this way. - */ - USB_STATE_NOTATTACHED = 0, + /* NOTATTACHED isn't in the USB spec, and this state acts + * the same as ATTACHED ... but it's clearer this way. + */ + USB_STATE_NOTATTACHED = 0, - /* chapter 9 and authentication (wireless) device states */ - USB_STATE_ATTACHED, - USB_STATE_POWERED, /* wired */ - USB_STATE_UNAUTHENTICATED, /* auth */ - USB_STATE_RECONNECTING, /* auth */ - USB_STATE_DEFAULT, /* limited function */ - USB_STATE_ADDRESS, - USB_STATE_CONFIGURED, /* most functions */ + /* chapter 9 and authentication (wireless) device states */ + USB_STATE_ATTACHED, + USB_STATE_POWERED, /* wired */ + USB_STATE_UNAUTHENTICATED, /* auth */ + USB_STATE_RECONNECTING, /* auth */ + USB_STATE_DEFAULT, /* limited function */ + USB_STATE_ADDRESS, + USB_STATE_CONFIGURED, /* most functions */ - USB_STATE_SUSPENDED + USB_STATE_SUSPENDED - /* NOTE: there are actually four different SUSPENDED - * states, returning to POWERED, DEFAULT, ADDRESS, or - * CONFIGURED respectively when SOF tokens flow again. - */ + /* NOTE: there are actually four different SUSPENDED + * states, returning to POWERED, DEFAULT, ADDRESS, or + * CONFIGURED respectively when SOF tokens flow again. + * At this level there's no difference between L1 and L2 + * suspend states. (L2 being original USB 1.1 suspend.) + */ }; -/* All standard descriptors have these 2 fields at the beginning */ -struct usb_descriptor_header { - uint8_t bLength; - uint8_t bDescriptorType; -} __attribute__ ((packed)); - /** * struct usb_string - wraps a C string and its USB id * @id:the (nonzero) ID for this string @@ -390,8 +417,8 @@ * together with its ID. */ struct usb_string { - uint8_t id; - const char* s; + uint8_t id; + const char* s; }; /** @@ -403,8 +430,8 @@ * strings for a given language. */ struct usb_gadget_strings { - uint16_t language; /* 0x0409 for en-us */ - struct usb_string* strings; + uint16_t language; /* 0x0409 for en-us */ + struct usb_string* strings; }; #endif /*_CH9_H_*/ Index: firmware/export/config-e200.h =================================================================== --- firmware/export/config-e200.h (revision 20720) +++ firmware/export/config-e200.h (working copy) @@ -178,6 +178,9 @@ #define USB_VENDOR_ID 0x0781 #define USB_PRODUCT_ID 0x7421 +#define USB_HID +#define USB_SERIAL + /* Virtual LED (icon) */ #define CONFIG_LED LED_VIRTUAL Index: firmware/export/config-ipodcolor.h =================================================================== --- firmware/export/config-ipodcolor.h (revision 20720) +++ firmware/export/config-ipodcolor.h (working copy) @@ -155,6 +155,10 @@ #define USB_VENDOR_ID 0x05ac #define USB_PRODUCT_ID 0x1204 +#define USB_SERIAL +#define USB_STORAGE +#define USB_HID + /* Virtual LED (icon) */ #define CONFIG_LED LED_VIRTUAL Index: firmware/export/usb_core.h =================================================================== --- firmware/export/usb_core.h (revision 20720) +++ firmware/export/usb_core.h (working copy) @@ -26,6 +26,7 @@ //#define USB_SERIAL #define USB_STORAGE #define USB_CHARGING_ONLY +//#define USB_HID #else /* BOOTLOADER */ #define USB_CHARGING_ONLY #endif /* BOOTLOADER */ @@ -45,10 +46,10 @@ void usb_core_transfer_complete(int endpoint, int dir, int status, int length); void usb_core_bus_reset(void); bool usb_core_any_exclusive_storage(void); -void usb_core_enable_driver(int driver,bool enabled); +void usb_core_enable_driver(int driver, bool enabled); bool usb_core_driver_enabled (int driver); void usb_core_handle_transfer_completion( - struct usb_transfer_completion_event_data* event); + struct usb_transfer_completion_event_data* event); int usb_core_ack_control(struct usb_ctrlrequest* req); int usb_core_request_endpoint(int dir, struct usb_class_driver *drv); Index: firmware/export/config-ipod4g.h =================================================================== --- firmware/export/config-ipod4g.h (revision 20720) +++ firmware/export/config-ipod4g.h (working copy) @@ -172,6 +172,9 @@ /* USB On-the-go */ #define CONFIG_USBOTG USBOTG_ARC +#define USB_SERIAL +// #define USB_HID + /* enable these for the experimental usb stack */ #define HAVE_USBSTACK #define USE_ROCKBOX_USB Index: firmware/export/usb.h =================================================================== --- firmware/export/usb.h (revision 20720) +++ firmware/export/usb.h (working copy) @@ -93,6 +93,7 @@ USB_DRIVER_MASS_STORAGE, USB_DRIVER_SERIAL, USB_DRIVER_CHARGING_ONLY, + USB_DRIVER_HID, USB_NUM_DRIVERS }; #endif @@ -107,7 +108,6 @@ }; #endif - void usb_init(void); void usb_enable(bool on); void usb_attach(void); @@ -128,7 +128,8 @@ #endif #endif #ifdef HAVE_USBSTACK -void usb_signal_transfer_completion(struct usb_transfer_completion_event_data* event_data); +void usb_signal_transfer_completion( + struct usb_transfer_completion_event_data *event_data); bool usb_driver_enabled(int driver); bool usb_exclusive_storage(void); /* storage is available for usb */ void usb_storage_try_release_storage(void); Index: firmware/usbstack/usb_class_driver.h =================================================================== --- firmware/usbstack/usb_class_driver.h (revision 20720) +++ firmware/usbstack/usb_class_driver.h (working copy) @@ -25,14 +25,14 @@ /* Common api, implemented by all class drivers */ struct usb_class_driver { - /* First some runtime data */ + /* First some runtime data */ bool enabled; int first_interface; int last_interface; - /* Driver api starts here */ + /* Driver api starts here */ - /* Set this to true if the driver needs exclusive disk access (e.g. usb storage) */ + /* Set this to true if the driver needs exclusive disk access (e.g. usb storage) */ bool needs_exclusive_storage; /* Let the driver request endpoints it need. Returns zero on success */ @@ -52,7 +52,7 @@ int (*get_config_descriptor)(unsigned char *dest, int max_packet_size); /* Tells the driver that a usb connection has been set up and is now - ready to use. + ready to use. Optional function */ void (*init_connection)(void); @@ -62,27 +62,33 @@ Optional function */ void (*init)(void); - /* Tells the driver that the usb connection is no longer active + /* Tells the driver that the usb connection is no longer active Optional function */ void (*disconnect)(void); /* Tells the driver that a usb transfer has been completed. Note that "dir" - is relative to the host + is relative to the host Optional function */ void (*transfer_complete)(int ep,int dir, int status, int length); /* Tells the driver that a control request has come in. If the driver is able to handle it, it should ack the request, and return true. Otherwise - it should return false. + it should return false. Optional function */ - bool (*control_request)(struct usb_ctrlrequest* req); + bool (*control_request)(struct usb_ctrlrequest* req, unsigned char *dest); #ifdef HAVE_HOTSWAP /* Tells the driver that a hotswappable disk/card was inserted or - extracted + extracted Optional function */ void (*notify_hotswap)(int volume, bool inserted); #endif }; +#define PACK_DESCRIPTOR(dest, descriptor) \ + do { \ + memcpy(dest, &(descriptor), sizeof(descriptor)); \ + dest += sizeof(descriptor); \ + } while (0) + #endif Index: firmware/usbstack/usb_core.c =================================================================== --- firmware/usbstack/usb_core.c (revision 20720) +++ firmware/usbstack/usb_core.c (working copy) @@ -43,6 +43,10 @@ #include "usb_charging_only.h" #endif +#if defined(USB_HID) +#include "usb_hid.h" +#endif + /* TODO: Move target-specific stuff somewhere else (serial number reading) */ #ifdef HAVE_AS3514 @@ -88,7 +92,7 @@ } ; static struct usb_config_descriptor __attribute__((aligned(2))) - config_descriptor = + config_descriptor = { .bLength = sizeof(struct usb_config_descriptor), .bDescriptorType = USB_DT_CONFIG, @@ -100,7 +104,6 @@ .bMaxPower = (USB_MAX_CURRENT+1) / 2, /* In 2mA units */ }; - static const struct usb_qualifier_descriptor __attribute__((aligned(2))) qualifier_descriptor = { @@ -168,7 +171,7 @@ static int usb_core_num_interfaces; typedef void (*completion_handler_t)(int ep,int dir, int status, int length); -typedef bool (*control_handler_t)(struct usb_ctrlrequest* req); +typedef bool (*control_handler_t)(struct usb_ctrlrequest* req, unsigned char *dest); static struct { @@ -235,14 +238,32 @@ .notify_hotswap = NULL, #endif }, +#ifdef USB_HID + [USB_DRIVER_HID] = { + .enabled = false, + .needs_exclusive_storage = false, + .first_interface = 0, + .last_interface = 0, + .request_endpoints = usb_hid_request_endpoints, + .set_first_interface = usb_hid_set_first_interface, + .get_config_descriptor = usb_hid_get_config_descriptor, + .init_connection = usb_hid_init_connection, + .init = usb_hid_init, + .disconnect = usb_hid_disconnect, + .transfer_complete = usb_hid_transfer_complete, + .control_request = usb_hid_control_request, +#ifdef HAVE_HOTSWAP + .notify_hotswap = NULL, #endif + }, +#endif +#endif }; static void usb_core_control_request_handler(struct usb_ctrlrequest* req); static unsigned char response_data[256] USB_DEVBSS_ATTR; - static short hex[16] = {'0','1','2','3','4','5','6','7', '8','9','A','B','C','D','E','F'}; #ifdef IPOD_ARCH @@ -357,15 +378,15 @@ for(i=0;iendpoint; switch(ep) { @@ -382,9 +404,9 @@ (struct usb_ctrlrequest*)event->data); break; default: - if(ep_data[ep].completion_handler[event->dir>>7] != NULL) - ep_data[ep].completion_handler[event->dir>>7](ep,event->dir, - event->status,event->length); + handler = ep_data[ep].completion_handler[event->dir>>7]; + if(handler != NULL) + handler(ep,event->dir,event->status,event->length); break; } } @@ -403,8 +425,7 @@ { int i; for(i=0;iwIndex) && + drivers[i].last_interface > (req->wIndex)) + { + handled = drivers[i].control_request(req, response_data); + if(handled) + break; + } } + if(!handled) { + /* nope. flag error */ + logf("bad req:desc %d:%d", req->bRequest, req->wValue>>8); + usb_drv_stall(EP_CONTROL, true,true); + usb_core_ack_control(req); + } +} - switch(req->bRequestType & 0x1f) { - case 0: /* Device */ - switch (req->bRequest) { - case USB_REQ_GET_CONFIGURATION: { - logf("usb_core: GET_CONFIG"); - if (usb_state == ADDRESS) - response_data[0] = 0; - else - response_data[0] = 1; - if(usb_drv_send(EP_CONTROL, response_data, 1)!= 0) - break; - usb_core_ack_control(req); - break; +static void request_handler_device_get_descriptor(struct usb_ctrlrequest* req) +{ + int size; + int index = req->wValue & 0xff; + int length = req->wLength; + const void* ptr = NULL; + + switch(req->wValue>>8) { /* type */ + case USB_DT_DEVICE: + ptr = &device_descriptor; + size = sizeof(struct usb_device_descriptor); + break; + + case USB_DT_OTHER_SPEED_CONFIG: + case USB_DT_CONFIG: { + int i, max_packet_size; + + if(req->wValue >> 8 == USB_DT_CONFIG) { + max_packet_size=(usb_drv_port_speed() ? 512 : 64); + config_descriptor.bDescriptorType=USB_DT_CONFIG; } - case USB_REQ_SET_CONFIGURATION: { - logf("usb_core: SET_CONFIG"); - usb_drv_cancel_all_transfers(); - if (req->wValue) { - usb_state = CONFIGURED; - for(i=0;iwValue; - logf("usb_core: SET_ADR %d", address); - if(usb_core_ack_control(req)!=0) - break; - usb_drv_cancel_all_transfers(); - usb_address = address; - usb_drv_set_address(usb_address); - usb_state = ADDRESS; - break; - } - case USB_REQ_GET_DESCRIPTOR: { - int index = req->wValue & 0xff; - int length = req->wLength; - int size; - const void* ptr = NULL; - logf("usb_core: GET_DESC %d", req->wValue >> 8); + config_descriptor.bNumInterfaces = + usb_core_num_interfaces; + config_descriptor.wTotalLength = size; + memcpy(&response_data[0],&config_descriptor, + sizeof(struct usb_config_descriptor)); - switch (req->wValue >> 8) { /* type */ - case USB_DT_DEVICE: - ptr = &device_descriptor; - size = sizeof(struct usb_device_descriptor); - break; + ptr = response_data; + break; + } - case USB_DT_OTHER_SPEED_CONFIG: - case USB_DT_CONFIG: { - int max_packet_size; + case USB_DT_STRING: + logf("STRING %d",index); + if ((unsigned)index < (sizeof(usb_strings)/ + sizeof(struct usb_string_descriptor*))) + { + size = usb_strings[index]->bLength; + ptr = usb_strings[index]; + } + else { + logf("bad string id %d", index); + usb_drv_stall(EP_CONTROL, true,true); + } + break; - if(req->wValue >> 8 == USB_DT_CONFIG) { - if(usb_drv_port_speed()) - max_packet_size=512; - else - max_packet_size=64; - config_descriptor.bDescriptorType=USB_DT_CONFIG; - } - else { - if(usb_drv_port_speed()) - max_packet_size=64; - else - max_packet_size=512; - config_descriptor.bDescriptorType = - USB_DT_OTHER_SPEED_CONFIG; - } - size = sizeof(struct usb_config_descriptor); + case USB_DT_DEVICE_QUALIFIER: + ptr = &qualifier_descriptor; + size = sizeof (struct usb_qualifier_descriptor); + break; - for(i=0;ibLength; - ptr = usb_strings[index]; - } - else { - logf("bad string id %d", index); - usb_drv_stall(EP_CONTROL, true,true); - } - break; + if (ptr != response_data) { + memcpy(response_data, ptr, length); + } - case USB_DT_DEVICE_QUALIFIER: - ptr = &qualifier_descriptor; - size = sizeof (struct usb_qualifier_descriptor); - break; + if(usb_drv_send(EP_CONTROL, response_data, length)) + return; + } + usb_core_ack_control(req); +} - default: - logf("bad desc %d", req->wValue >> 8); - usb_drv_stall(EP_CONTROL, true,true); - break; - } +static void request_handler_device(struct usb_ctrlrequest* req) +{ + int i; - if (ptr) { - length = MIN(size, length); - - if (ptr != response_data) { - memcpy(response_data, ptr, length); - } - - if(usb_drv_send(EP_CONTROL, response_data, length)!=0) - break; - } + switch(req->bRequest) { + case USB_REQ_GET_CONFIGURATION: { + logf("usb_core: GET_CONFIG"); + response_data[0] = (usb_state == ADDRESS ? 0 : 1); + if(usb_drv_send(EP_CONTROL, response_data, 1)== 0) usb_core_ack_control(req); - break; - } /* USB_REQ_GET_DESCRIPTOR */ - case USB_REQ_CLEAR_FEATURE: - break; - case USB_REQ_SET_FEATURE: - if(req->wValue == 2) { /* TEST_MODE */ - int mode=req->wIndex>>8; - usb_core_ack_control(req); - usb_drv_set_test_mode(mode); - } - break; - case USB_REQ_GET_STATUS: - response_data[0]= 0; - response_data[1]= 0; - if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) - break; - usb_core_ack_control(req); - break; - default: - break; + break; } - break; - case 1: /* Interface */ - switch (req->bRequest) { - case USB_REQ_SET_INTERFACE: - logf("usb_core: SET_INTERFACE"); - usb_core_ack_control(req); - break; - - case USB_REQ_GET_INTERFACE: - logf("usb_core: GET_INTERFACE"); - response_data[0] = 0; - if(usb_drv_send(EP_CONTROL, response_data, 1)!=0) - break; - usb_core_ack_control(req); - break; - case USB_REQ_CLEAR_FEATURE: - break; - case USB_REQ_SET_FEATURE: - break; - case USB_REQ_GET_STATUS: - response_data[0]= 0; - response_data[1]= 0; - if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) - break; - usb_core_ack_control(req); - break; - default: { - bool handled=false; + case USB_REQ_SET_CONFIGURATION: { + logf("usb_core: SET_CONFIG"); + usb_drv_cancel_all_transfers(); + if(req->wValue) { + usb_state = CONFIGURED; for(i=0;iwIndex) && - drivers[i].last_interface > (req->wIndex)) + if(drivers[i].enabled && drivers[i].init_connection) { - handled = drivers[i].control_request(req); + drivers[i].init_connection(); } } - if(!handled) { - /* nope. flag error */ - logf("usb bad req %d", req->bRequest); - usb_drv_stall(EP_CONTROL, true,true); - usb_core_ack_control(req); - } - break; } + else { + usb_state = ADDRESS; + } + usb_core_ack_control(req); + break; } + case USB_REQ_SET_ADDRESS: { + unsigned char address = req->wValue; + logf("usb_core: SET_ADR %d", address); + if(usb_core_ack_control(req)!=0) + break; + usb_drv_cancel_all_transfers(); + usb_address = address; + usb_drv_set_address(usb_address); + usb_state = ADDRESS; + break; + } + case USB_REQ_GET_DESCRIPTOR: + logf("usb_core: GET_DESC %d", req->wValue>>8); + request_handler_device_get_descriptor(req); break; - case 2: /* Endpoint */ - switch (req->bRequest) { - case USB_REQ_CLEAR_FEATURE: - if (req->wValue == 0 ) /* ENDPOINT_HALT */ - usb_drv_stall(req->wIndex & 0xf, false, - (req->wIndex & 0x80) !=0); - usb_core_ack_control(req); + case USB_REQ_CLEAR_FEATURE: + break; + case USB_REQ_SET_FEATURE: + if(req->wValue == 2) { /* TEST_MODE */ + int mode=req->wIndex>>8; + usb_core_ack_control(req); + usb_drv_set_test_mode(mode); + } + break; + case USB_REQ_GET_STATUS: + response_data[0]= 0; + response_data[1]= 0; + if(usb_drv_send(EP_CONTROL, response_data, 2)==0) + usb_core_ack_control(req); + break; + default: + break; + } +} + +static void request_handler_interface_standard(struct usb_ctrlrequest *req) +{ + switch (req->bRequest) + { + case USB_REQ_SET_INTERFACE: + logf("usb_core: SET_INTERFACE"); + usb_core_ack_control(req); + break; + + case USB_REQ_GET_INTERFACE: + logf("usb_core: GET_INTERFACE"); + response_data[0] = 0; + if(usb_drv_send(EP_CONTROL, response_data, 1)==0) + usb_core_ack_control(req); + break; + case USB_REQ_CLEAR_FEATURE: + break; + case USB_REQ_SET_FEATURE: + break; + case USB_REQ_GET_STATUS: + response_data[0]= 0; + response_data[1]= 0; + if(usb_drv_send(EP_CONTROL, response_data, 2)==0) + usb_core_ack_control(req); + break; + default: + logf("ctrl if. std."); + control_request_handler_drivers(req); + break; + } +} + +static void request_handler_interface(struct usb_ctrlrequest *req) +{ + switch(req->bRequestType & USB_TYPE_MASK) { + case USB_TYPE_STANDARD: + request_handler_interface_standard(req); + break; + case USB_TYPE_CLASS: + logf("ctrl if. cls."); + control_request_handler_drivers(req); + break; + case USB_TYPE_VENDOR: + break; + } +} + +static void request_handler_endpoint(struct usb_ctrlrequest *req) +{ + switch (req->bRequest) { + case USB_REQ_CLEAR_FEATURE: + if (req->wValue == 0) { /* ENDPOINT_HALT */ + usb_drv_stall(req->wIndex & 0xf, false, + (req->wIndex & USB_DIR_IN)!=0); + } + usb_core_ack_control(req); + break; + case USB_REQ_SET_FEATURE: + if (req->wValue == 0) { /* ENDPOINT_HALT */ + usb_drv_stall(req->wIndex & 0xf, true, + (req->wIndex & USB_DIR_IN)!=0); + } + usb_core_ack_control(req); + break; + case USB_REQ_GET_STATUS: + response_data[0]= 0; + response_data[1]= 0; + logf("usb_core: GET_STATUS"); + if(req->wIndex>0) { + response_data[0] = usb_drv_stalled(req->wIndex&0xf, + (req->wIndex&USB_DIR_IN)!=0); + } + if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) + break; + usb_core_ack_control(req); + break; + default: { + control_handler_t control_handler; + bool handled; + + control_handler = ep_data[req->wIndex & 0xf].control_handler[0]; + if (!control_handler) break; - case USB_REQ_SET_FEATURE: - if (req->wValue == 0 ) /* ENDPOINT_HALT */ - usb_drv_stall(req->wIndex & 0xf, true, - (req->wIndex & 0x80) !=0); - usb_core_ack_control(req); + + handled = control_handler(req, response_data); + if (handled) break; - case USB_REQ_GET_STATUS: - response_data[0]= 0; - response_data[1]= 0; - logf("usb_core: GET_STATUS"); - if(req->wIndex>0) - response_data[0] = usb_drv_stalled(req->wIndex&0xf, - (req->wIndex&0x80)!=0); - if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) - break; - usb_core_ack_control(req); - break; - default: { - bool handled=false; - if(ep_data[req->wIndex & 0xf].control_handler[0] != NULL) - handled = ep_data[req->wIndex & 0xf].control_handler[0](req); - if(!handled) { - /* nope. flag error */ - logf("usb bad req %d", req->bRequest); - usb_drv_stall(EP_CONTROL, true,true); - usb_core_ack_control(req); - } - break; - } + + /* nope. flag error */ + logf("usb bad req %d", req->bRequest); + usb_drv_stall(EP_CONTROL, true,true); + usb_core_ack_control(req); + break; } } - logf("control handled"); } +static void usb_core_control_request_handler(struct usb_ctrlrequest* req) +{ + if (usb_state == DEFAULT) { + set_serial_descriptor(); + usb_core_set_serial_function_id(); + + allocate_interfaces_and_endpoints(); + } + + switch(req->bRequestType & USB_RECIP_MASK) { + case USB_RECIP_DEVICE: + request_handler_device(req); + break; + case USB_RECIP_INTERFACE: + request_handler_interface(req); + break; + case USB_RECIP_ENDPOINT: + request_handler_endpoint(req); + break; + case USB_RECIP_OTHER: + logf("unsupported recipient"); + break; + } + //logf("control handled"); +} + /* called by usb_drv_int() */ void usb_core_bus_reset(void) { @@ -760,19 +824,23 @@ /* called by usb_drv_transfer_completed() */ void usb_core_transfer_complete(int endpoint, int dir, int status,int length) { + struct usb_transfer_completion_event_data *completion_event; + switch (endpoint) { case EP_CONTROL: /* already handled */ break; default: - ep_data[endpoint].completion_event.endpoint=endpoint; - ep_data[endpoint].completion_event.dir=dir; - ep_data[endpoint].completion_event.data=0; - ep_data[endpoint].completion_event.status=status; - ep_data[endpoint].completion_event.length=length; + completion_event = &ep_data[endpoint].completion_event; + + completion_event->endpoint=endpoint; + completion_event->dir=dir; + completion_event->data=0; + completion_event->status=status; + completion_event->length=length; /* All other endoints. Let the thread deal with it */ - usb_signal_transfer_completion(&ep_data[endpoint].completion_event); + usb_signal_transfer_completion(completion_event); break; } } @@ -780,18 +848,21 @@ /* called by usb_drv_int() */ void usb_core_control_request(struct usb_ctrlrequest* req) { - ep_data[0].completion_event.endpoint=0; - ep_data[0].completion_event.dir=0; - ep_data[0].completion_event.data=(void *)req; - ep_data[0].completion_event.status=0; - ep_data[0].completion_event.length=0; + struct usb_transfer_completion_event_data *completion_event = + &ep_data[0].completion_event; + + completion_event->endpoint=0; + completion_event->dir=0; + completion_event->data=(void *)req; + completion_event->status=0; + completion_event->length=0; logf("ctrl received %ld",current_tick); - usb_signal_transfer_completion(&ep_data[0].completion_event); + usb_signal_transfer_completion(completion_event); } int usb_core_ack_control(struct usb_ctrlrequest* req) { - if (req->bRequestType & 0x80) + if (req->bRequestType & USB_DIR_IN) return usb_drv_recv(EP_CONTROL, NULL, 0); else return usb_drv_send(EP_CONTROL, NULL, 0); @@ -800,13 +871,6 @@ #ifdef HAVE_USB_POWER unsigned short usb_allowed_current() { - if (usb_state == CONFIGURED) - { - return MAX(USB_MAX_CURRENT, 100); - } - else - { - return 100; - } + return (usb_state == CONFIGURED) ? MAX(USB_MAX_CURRENT, 100) : 100; } #endif Index: firmware/usbstack/usb_storage.h =================================================================== --- firmware/usbstack/usb_storage.h (revision 20720) +++ firmware/usbstack/usb_storage.h (working copy) @@ -30,7 +30,7 @@ void usb_storage_disconnect(void); void usb_storage_init(void); void usb_storage_transfer_complete(int ep,int dir,int state,int length); -bool usb_storage_control_request(struct usb_ctrlrequest* req); +bool usb_storage_control_request(struct usb_ctrlrequest* req, unsigned char* dest); #ifdef HAVE_HOTSWAP void usb_storage_notify_hotswap(int volume,bool inserted); #endif Index: firmware/usbstack/usb_hid.h =================================================================== --- firmware/usbstack/usb_hid.h (revision 0) +++ firmware/usbstack/usb_hid.h (revision 0) @@ -0,0 +1,38 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 by Tomer Shalev + * + * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef USB_HID_H +#define USB_HID_H + +#include "usb_ch9.h" + +int usb_hid_request_endpoints(struct usb_class_driver *drv); +int usb_hid_set_first_interface(int interface); +int usb_hid_get_config_descriptor(unsigned char *dest, int max_packet_size); +void usb_hid_init_connection(void); +void usb_hid_init(void); +void usb_hid_disconnect(void); +void usb_hid_transfer_complete(int ep, int dir, int status, int length); +bool usb_hid_control_request(struct usb_ctrlrequest* req, unsigned char* dest); + +void usb_hid_send(unsigned char *data,int length); + +#endif + Index: firmware/usbstack/usb_serial.c =================================================================== --- firmware/usbstack/usb_serial.c (revision 20720) +++ firmware/usbstack/usb_serial.c (working copy) @@ -24,7 +24,7 @@ #include "usb_drv.h" #include "kernel.h" #include "usb_serial.h" - +#include "usb_class_driver.h" //#define LOGF_ENABLE #include "logf.h" @@ -32,7 +32,7 @@ /* serial interface */ static struct usb_interface_descriptor __attribute__((aligned(2))) - interface_descriptor = + interface_descriptor = { .bLength = sizeof(struct usb_interface_descriptor), .bDescriptorType = USB_DT_INTERFACE, @@ -46,7 +46,8 @@ }; -static struct usb_endpoint_descriptor __attribute__((aligned(2))) endpoint_descriptor = +static struct usb_endpoint_descriptor __attribute__((aligned(2))) + endpoint_descriptor = { .bLength = sizeof(struct usb_endpoint_descriptor), .bDescriptorType = USB_DT_ENDPOINT, @@ -77,12 +78,10 @@ int usb_serial_request_endpoints(struct usb_class_driver *drv) { ep_in = usb_core_request_endpoint(USB_DIR_IN, drv); - if (ep_in < 0) return -1; - - ep_out = usb_core_request_endpoint(USB_DIR_OUT, drv); + ep_out = usb_core_request_endpoint(USB_DIR_OUT, drv); if (ep_out < 0) { usb_core_release_endpoint(ep_in); return -1; @@ -94,38 +93,37 @@ int usb_serial_set_first_interface(int interface) { usb_interface = interface; + return interface + 1; } - -int usb_serial_get_config_descriptor(unsigned char *dest,int max_packet_size) +int usb_serial_get_config_descriptor(unsigned char *dest, int max_packet_size) { unsigned char *orig_dest = dest; - endpoint_descriptor.wMaxPacketSize=max_packet_size; - interface_descriptor.bInterfaceNumber=usb_interface; + interface_descriptor.bInterfaceNumber = usb_interface; + PACK_DESCRIPTOR(dest, interface_descriptor); - memcpy(dest,&interface_descriptor,sizeof(struct usb_interface_descriptor)); - dest+=sizeof(struct usb_interface_descriptor); + endpoint_descriptor.wMaxPacketSize = max_packet_size; endpoint_descriptor.bEndpointAddress = ep_in; - memcpy(dest,&endpoint_descriptor,sizeof(struct usb_endpoint_descriptor)); - dest+=sizeof(struct usb_endpoint_descriptor); + PACK_DESCRIPTOR(dest, endpoint_descriptor); endpoint_descriptor.bEndpointAddress = ep_out; - memcpy(dest,&endpoint_descriptor,sizeof(struct usb_endpoint_descriptor)); - dest+=sizeof(struct usb_endpoint_descriptor); + PACK_DESCRIPTOR(dest, endpoint_descriptor); return (dest - orig_dest); } /* called by usb_core_control_request() */ -bool usb_serial_control_request(struct usb_ctrlrequest* req) +bool usb_serial_control_request(struct usb_ctrlrequest* req, unsigned char* dest) { bool handled = false; + + (void)dest; switch (req->bRequest) { default: - logf("serial: unhandeld req %d", req->bRequest); + logf("serial: unhandeld req %u", req->bRequest); } return handled; } @@ -137,11 +135,11 @@ /* we come here too after a bus reset, so reset some data */ buffer_transitlength = 0; - if(buffer_length>0) + if (buffer_length > 0) { sendout(); } - active=true; + active = true; } /* called by usb_code_init() */ @@ -161,19 +159,10 @@ static void sendout(void) { - if(buffer_start+buffer_length >= BUFFER_SIZE) + buffer_transitlength = MIN(buffer_length,BUFFER_SIZE-buffer_start); + if(buffer_transitlength > 0) { - /* Buffer wraps. Only send the first part */ - buffer_transitlength=BUFFER_SIZE - buffer_start; - } - else - { - /* Send everything */ - buffer_transitlength=buffer_length; - } - if(buffer_transitlength>0) - { - buffer_length-=buffer_transitlength; + buffer_length -= buffer_transitlength; usb_drv_send_nonblocking(ep_in, &send_buffer[buffer_start], buffer_transitlength); } @@ -181,25 +170,30 @@ void usb_serial_send(unsigned char *data,int length) { - if(!active) + int freestart, available_end_space, i; + + if (!active||length<=0) return; - if(length<=0) - return; - int freestart=(buffer_start+buffer_length+buffer_transitlength)%BUFFER_SIZE; - if(buffer_start+buffer_transitlength+buffer_length >= BUFFER_SIZE) - { - /* current buffer wraps, so new data can't */ - int available_space = BUFFER_SIZE - buffer_length - buffer_transitlength; - length=MIN(length,available_space); - memcpy(&send_buffer[freestart], - data,length); - buffer_length+=length; + + i=buffer_start+buffer_length+buffer_transitlength; + freestart=i%BUFFER_SIZE; + available_end_space=BUFFER_SIZE-i; + + if (0>=available_end_space) + { + /* current buffer wraps, so new data can't wrap */ + int available_space = BUFFER_SIZE - + (buffer_length + buffer_transitlength); + + length = MIN(length, available_space); + memcpy(&send_buffer[freestart], data, length); + buffer_length += length; } else { /* current buffer doesn't wrap, so new data might */ - int available_end_space = (BUFFER_SIZE - (buffer_start+buffer_length+buffer_transitlength)); int first_chunk = MIN(length,available_end_space); + memcpy(&send_buffer[freestart],data,first_chunk); length-=first_chunk; buffer_length+=first_chunk; @@ -210,20 +204,18 @@ buffer_length+=MIN(length,buffer_start); } } - if(buffer_transitlength>0) - { - /* Do nothing. The transfer completion handler will pick it up */ - } - else - { + + if (buffer_transitlength==0) sendout(); - } + /* else do nothing. The transfer completion handler will pick it up */ } /* called by usb_core_transfer_complete() */ void usb_serial_transfer_complete(int ep,int dir, int status, int length) { (void)ep; + (void)length; + switch (dir) { case USB_DIR_OUT: logf("serial: %s", receive_buffer); @@ -237,21 +229,16 @@ /* Data sent out. Update circular buffer */ if(status == 0) { - if(length!=buffer_transitlength) - { - /* do something? */ - } - buffer_start = (buffer_start + buffer_transitlength)%BUFFER_SIZE; + /* TODO: Handle (length != buffer_transitlength) */ + + buffer_start=(buffer_start+buffer_transitlength)%BUFFER_SIZE; buffer_transitlength = 0; } if(buffer_length>0) - { sendout(); - } break; } } - #endif /*USB_SERIAL*/ Index: firmware/usbstack/usb_charging_only.c =================================================================== --- firmware/usbstack/usb_charging_only.c (revision 20720) +++ firmware/usbstack/usb_charging_only.c (working copy) @@ -24,6 +24,7 @@ #include "usb_drv.h" #include "kernel.h" #include "usb_charging_only.h" +#include "usb_class_driver.h" //#define LOGF_ENABLE #include "logf.h" @@ -45,7 +46,6 @@ .iInterface = 0 }; - static int usb_interface; int usb_charging_only_request_endpoints(struct usb_class_driver *drv) @@ -66,10 +66,8 @@ unsigned char *orig_dest = dest; interface_descriptor.bInterfaceNumber=usb_interface; - memcpy(dest,&interface_descriptor,sizeof(struct usb_interface_descriptor)); + PACK_DESCRIPTOR(dest, interface_descriptor); - dest+=sizeof(struct usb_interface_descriptor); - return (dest-orig_dest); } Index: firmware/usbstack/usb_serial.h =================================================================== --- firmware/usbstack/usb_serial.h (revision 20720) +++ firmware/usbstack/usb_serial.h (working copy) @@ -30,7 +30,7 @@ void usb_serial_init(void); void usb_serial_disconnect(void); void usb_serial_transfer_complete(int ep,int dir, int status, int length); -bool usb_serial_control_request(struct usb_ctrlrequest* req); +bool usb_serial_control_request(struct usb_ctrlrequest* req, unsigned char *dest); void usb_serial_send(unsigned char *data,int length); Index: firmware/usbstack/usb_storage.c =================================================================== --- firmware/usbstack/usb_storage.c (revision 20720) +++ firmware/usbstack/usb_storage.c (working copy) @@ -22,6 +22,7 @@ #include "system.h" #include "usb_core.h" #include "usb_drv.h" +#include "usb_class_driver.h" //#define LOGF_ENABLE #include "logf.h" #include "storage.h" @@ -53,12 +54,14 @@ */ #define BUFFER_SIZE 65536 +#define SECTORS (BUFFER_SIZE / SECTOR_SIZE) + /* bulk-only class specific requests */ #define USB_BULK_RESET_REQUEST 0xff #define USB_BULK_GET_MAX_LUN 0xfe -#define DIRECT_ACCESS_DEVICE 0x00 /* disks */ -#define DEVICE_REMOVABLE 0x80 +#define DIRECT_ACCESS_DEVICE 0x00 /* disks */ +#define DEVICE_REMOVABLE 0x80 #define CBW_SIGNATURE 0x43425355 #define CSW_SIGNATURE 0x53425355 @@ -102,7 +105,7 @@ #define USB_PROT_BULK 0x50 /* bulk only */ static struct usb_interface_descriptor __attribute__((aligned(2))) - interface_descriptor = + interface_descriptor = { .bLength = sizeof(struct usb_interface_descriptor), .bDescriptorType = USB_DT_INTERFACE, @@ -130,7 +133,7 @@ unsigned char DeviceType; unsigned char DeviceTypeModifier; unsigned char Versions; - unsigned char Format; + unsigned char Format; unsigned char AdditionalLength; unsigned char Reserved[2]; unsigned char Capability; @@ -308,12 +311,12 @@ void usb_storage_try_release_storage(void) { - /* Check if there is a connected drive left. If not, + /* Check if there is a connected drive left. If not, release excusive access */ bool canrelease=true; int i; for(i=0;isignature) == CBW_SIGNATURE){ + if(letoh32(cbw->signature) == CBW_SIGNATURE) { handle_scsi(cbw); } else { @@ -596,11 +590,11 @@ } /* called by usb_core_control_request() */ -bool usb_storage_control_request(struct usb_ctrlrequest* req) +bool usb_storage_control_request(struct usb_ctrlrequest* req, unsigned char* dest) { bool handled = false; - + (void)dest; switch (req->bRequest) { case USB_BULK_GET_MAX_LUN: { #ifdef ONLY_EXPOSE_CARD_SLOT @@ -625,7 +619,6 @@ usb_drv_reset_endpoint(ep_in, false); usb_drv_reset_endpoint(ep_out, true); #endif - usb_drv_send(EP_CONTROL, NULL, 0); /* ack */ handled = true; break; @@ -650,22 +643,20 @@ /* Switch buffers for the next one */ cur_cmd.data_select=!cur_cmd.data_select; - cur_cmd.sector+=(BUFFER_SIZE/SECTOR_SIZE); - cur_cmd.count-=MIN(cur_cmd.count,BUFFER_SIZE/SECTOR_SIZE); + cur_cmd.sector+=SECTORS; + cur_cmd.count-=MIN(cur_cmd.count,SECTORS); - if(cur_cmd.count!=0){ + if(cur_cmd.count!=0) { /* already read the next bit, so we can send it out immediately when the * current transfer completes. */ #ifdef USB_USE_RAMDISK memcpy(cur_cmd.data[cur_cmd.data_select], - ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, - MIN(BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); + ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, + MIN(SECTORS, cur_cmd.count)*SECTOR_SIZE); #else cur_cmd.last_result = storage_read_sectors(cur_cmd.lun, - cur_cmd.sector, - MIN(BUFFER_SIZE/SECTOR_SIZE, - cur_cmd.count), - cur_cmd.data[cur_cmd.data_select]); + cur_cmd.sector, MIN(SECTORS, cur_cmd.count), + cur_cmd.data[cur_cmd.data_select]); #endif } } @@ -784,7 +775,7 @@ } case SCSI_MODE_SENSE_10: { - if(! lun_present) { + if(!lun_present) { send_command_failed_result(); cur_sense_data.sense_key=SENSE_NOT_READY; cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; @@ -797,7 +788,7 @@ switch(page_code) { case 0x3f: tb.ms_data_10->mode_data_length = - htobe16(sizeof(struct mode_sense_data_10)-2); + htobe16(sizeof(struct mode_sense_data_10)-2); tb.ms_data_10->medium_type = 0; tb.ms_data_10->device_specific = 0; tb.ms_data_10->reserved = 0; @@ -809,24 +800,24 @@ memset(tb.ms_data_10->block_descriptor.num_blocks,0,8); tb.ms_data_10->block_descriptor.num_blocks[4] = - ((block_count/block_size_mult) & 0xff000000)>>24; + ((block_count/block_size_mult) & 0xff000000)>>24; tb.ms_data_10->block_descriptor.num_blocks[5] = - ((block_count/block_size_mult) & 0x00ff0000)>>16; + ((block_count/block_size_mult) & 0x00ff0000)>>16; tb.ms_data_10->block_descriptor.num_blocks[6] = - ((block_count/block_size_mult) & 0x0000ff00)>>8; + ((block_count/block_size_mult) & 0x0000ff00)>>8; tb.ms_data_10->block_descriptor.num_blocks[7] = - ((block_count/block_size_mult) & 0x000000ff); + ((block_count/block_size_mult) & 0x000000ff); tb.ms_data_10->block_descriptor.block_size[0] = - ((block_size*block_size_mult) & 0xff000000)>>24; + ((block_size*block_size_mult) & 0xff000000)>>24; tb.ms_data_10->block_descriptor.block_size[1] = - ((block_size*block_size_mult) & 0x00ff0000)>>16; + ((block_size*block_size_mult) & 0x00ff0000)>>16; tb.ms_data_10->block_descriptor.block_size[2] = - ((block_size*block_size_mult) & 0x0000ff00)>>8; + ((block_size*block_size_mult) & 0x0000ff00)>>8; tb.ms_data_10->block_descriptor.block_size[3] = - ((block_size*block_size_mult) & 0x000000ff); + ((block_size*block_size_mult) & 0x000000ff); send_command_result(tb.ms_data_10, - MIN(sizeof(struct mode_sense_data_10), length)); + MIN(sizeof(struct mode_sense_data_10), length)); break; default: send_command_failed_result(); @@ -834,11 +825,12 @@ cur_sense_data.asc=ASC_INVALID_FIELD_IN_CBD; cur_sense_data.ascq=0; break; - } + } break; } + case SCSI_MODE_SENSE_6: { - if(! lun_present) { + if(!lun_present) { send_command_failed_result(); cur_sense_data.sense_key=SENSE_NOT_READY; cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; @@ -852,34 +844,34 @@ case 0x3f: /* All supported pages. */ tb.ms_data_6->mode_data_length = - sizeof(struct mode_sense_data_6)-1; + sizeof(struct mode_sense_data_6)-1; tb.ms_data_6->medium_type = 0; tb.ms_data_6->device_specific = 0; tb.ms_data_6->block_descriptor_length = - sizeof(struct mode_sense_bdesc_shortlba); + sizeof(struct mode_sense_bdesc_shortlba); tb.ms_data_6->block_descriptor.density_code = 0; tb.ms_data_6->block_descriptor.reserved = 0; - if(block_count/block_size_mult > 0xffffff){ + if(block_count/block_size_mult > 0xffffff) { tb.ms_data_6->block_descriptor.num_blocks[0] = 0xff; tb.ms_data_6->block_descriptor.num_blocks[1] = 0xff; tb.ms_data_6->block_descriptor.num_blocks[2] = 0xff; } else { tb.ms_data_6->block_descriptor.num_blocks[0] = - ((block_count/block_size_mult) & 0xff0000)>>16; + ((block_count/block_size_mult) & 0xff0000)>>16; tb.ms_data_6->block_descriptor.num_blocks[1] = - ((block_count/block_size_mult) & 0x00ff00)>>8; + ((block_count/block_size_mult) & 0x00ff00)>>8; tb.ms_data_6->block_descriptor.num_blocks[2] = - ((block_count/block_size_mult) & 0x0000ff); + ((block_count/block_size_mult) & 0x0000ff); } tb.ms_data_6->block_descriptor.block_size[0] = - ((block_size*block_size_mult) & 0xff0000)>>16; + ((block_size*block_size_mult) & 0xff0000)>>16; tb.ms_data_6->block_descriptor.block_size[1] = - ((block_size*block_size_mult) & 0x00ff00)>>8; + ((block_size*block_size_mult) & 0x00ff00)>>8; tb.ms_data_6->block_descriptor.block_size[2] = - ((block_size*block_size_mult) & 0x0000ff); + ((block_size*block_size_mult) & 0x0000ff); send_command_result(tb.ms_data_6, - MIN(sizeof(struct mode_sense_data_6), length)); + MIN(sizeof(struct mode_sense_data_6), length)); break; default: send_command_failed_result(); @@ -910,57 +902,55 @@ case SCSI_ALLOW_MEDIUM_REMOVAL: logf("scsi allow_medium_removal %d",lun); - if((cbw->command_block[4] & 0x03) == 0) - { + if((cbw->command_block[4] & 0x03) == 0) { locked[lun]=false; queue_broadcast(SYS_USB_LUN_LOCKED, (lun<<16)+0); } - else - { + else { locked[lun]=true; queue_broadcast(SYS_USB_LUN_LOCKED, (lun<<16)+1); } send_csw(UMS_STATUS_GOOD); break; + case SCSI_READ_FORMAT_CAPACITY: { logf("scsi read_format_capacity %d",lun); if(lun_present) { tb.format_capacity_data->following_length=htobe32(8); /* "block count" actually means "number of last block" */ tb.format_capacity_data->block_count = - htobe32(block_count/block_size_mult - 1); + htobe32(block_count/block_size_mult - 1); tb.format_capacity_data->block_size = - htobe32(block_size*block_size_mult); + htobe32(block_size*block_size_mult); tb.format_capacity_data->block_size |= - htobe32(SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA); + htobe32(SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA); send_command_result(tb.format_capacity_data, - MIN(sizeof(struct format_capacity), length)); - } - else - { - send_command_failed_result(); - cur_sense_data.sense_key=SENSE_NOT_READY; - cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; - cur_sense_data.ascq=0; - } - break; + MIN(sizeof(struct format_capacity), length)); + } + else { + send_command_failed_result(); + cur_sense_data.sense_key=SENSE_NOT_READY; + cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; + cur_sense_data.ascq=0; + } + break; } + case SCSI_READ_CAPACITY: { logf("scsi read_capacity %d",lun); if(lun_present) { /* "block count" actually means "number of last block" */ tb.capacity_data->block_count = - htobe32(block_count/block_size_mult - 1); + htobe32(block_count/block_size_mult - 1); tb.capacity_data->block_size = - htobe32(block_size*block_size_mult); + htobe32(block_size*block_size_mult); send_command_result(tb.capacity_data, - MIN(sizeof(struct capacity), length)); + MIN(sizeof(struct capacity), length)); } - else - { + else { send_command_failed_result(); cur_sense_data.sense_key=SENSE_NOT_READY; cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; @@ -971,7 +961,7 @@ case SCSI_READ_10: logf("scsi read10 %d",lun); - if(! lun_present) { + if(!lun_present) { send_command_failed_result(); cur_sense_data.sense_key=SENSE_NOT_READY; cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; @@ -982,13 +972,13 @@ cur_cmd.data[1] = &tb.transfer_buffer[BUFFER_SIZE]; cur_cmd.data_select=0; cur_cmd.sector = block_size_mult * - (cbw->command_block[2] << 24 | - cbw->command_block[3] << 16 | - cbw->command_block[4] << 8 | - cbw->command_block[5] ); + (cbw->command_block[2] << 24 | + cbw->command_block[3] << 16 | + cbw->command_block[4] << 8 | + cbw->command_block[5] ); cur_cmd.count = block_size_mult * - (cbw->command_block[7] << 8 | - cbw->command_block[8]); + (cbw->command_block[7] << 8 | + cbw->command_block[8]); cur_cmd.orig_count = cur_cmd.count; //logf("scsi read %d %d", cur_cmd.sector, cur_cmd.count); @@ -1002,17 +992,15 @@ else { #ifdef USB_USE_RAMDISK memcpy(cur_cmd.data[cur_cmd.data_select], - ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, - MIN(BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); + ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, + MIN(SECTORS, cur_cmd.count)*SECTOR_SIZE); #else cur_cmd.last_result = storage_read_sectors(cur_cmd.lun, - cur_cmd.sector, - MIN(BUFFER_SIZE/SECTOR_SIZE, - cur_cmd.count), - cur_cmd.data[cur_cmd.data_select]); + cur_cmd.sector, MIN(SECTORS, cur_cmd.count), + cur_cmd.data[cur_cmd.data_select]); #ifdef TOSHIBA_GIGABEAT_S - if (cur_cmd.sector == 0) { + if(cur_cmd.sector == 0) { fix_mbr(cur_cmd.data[cur_cmd.data_select]); } #endif @@ -1023,7 +1011,7 @@ case SCSI_WRITE_10: logf("scsi write10 %d",lun); - if(! lun_present) { + if(!lun_present) { send_csw(UMS_STATUS_FAIL); cur_sense_data.sense_key=SENSE_NOT_READY; cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; @@ -1034,13 +1022,13 @@ cur_cmd.data[1] = &tb.transfer_buffer[BUFFER_SIZE]; cur_cmd.data_select=0; cur_cmd.sector = block_size_mult * - (cbw->command_block[2] << 24 | - cbw->command_block[3] << 16 | - cbw->command_block[4] << 8 | - cbw->command_block[5] ); + (cbw->command_block[2] << 24 | + cbw->command_block[3] << 16 | + cbw->command_block[4] << 8 | + cbw->command_block[5] ); cur_cmd.count = block_size_mult * - (cbw->command_block[7] << 8 | - cbw->command_block[8]); + (cbw->command_block[7] << 8 | + cbw->command_block[8]); cur_cmd.orig_count = cur_cmd.count; /* expect data */ @@ -1052,10 +1040,8 @@ } else { receive_block_data(cur_cmd.data[0], - MIN(BUFFER_SIZE, - cur_cmd.count*SECTOR_SIZE)); + MIN(BUFFER_SIZE, cur_cmd.count*SECTOR_SIZE)); } - break; default: @@ -1100,7 +1086,7 @@ tb.csw->status = status; usb_drv_send_nonblocking(ep_in, tb.csw, - sizeof(struct command_status_wrapper)); + sizeof(struct command_status_wrapper)); state = SENDING_CSW; //logf("CSW: %X",status); @@ -1130,8 +1116,8 @@ /* build SCSI INQUIRY */ static void fill_inquiry(IF_MV_NONVOID(int lun)) { - memset(tb.inquiry, 0, sizeof(struct inquiry_data)); struct storage_info info; + memset(tb.inquiry, 0, sizeof(struct inquiry_data)); storage_get_info(lun,&info); copy_padded(tb.inquiry->VendorId,info.vendor,sizeof(tb.inquiry->VendorId)); copy_padded(tb.inquiry->ProductId,info.product,sizeof(tb.inquiry->ProductId)); @@ -1141,7 +1127,7 @@ tb.inquiry->AdditionalLength = 0x1f; memset(tb.inquiry->Reserved, 0, 3); tb.inquiry->Versions = 4; /* SPC-2 */ - tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */ + tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */ #ifdef TOSHIBA_GIGABEAT_S tb.inquiry->DeviceTypeModifier = 0; Index: firmware/usbstack/usb_hid.c =================================================================== --- firmware/usbstack/usb_hid.c (revision 0) +++ firmware/usbstack/usb_hid.c (revision 0) @@ -0,0 +1,288 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 by Tomer Shalev + * + * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "string.h" +#include "system.h" +#include "usb_core.h" +#include "usb_drv.h" +#include "kernel.h" +#include "usb_hid.h" +#include "usb_class_driver.h" +//#define LOGF_ENABLE +#include "logf.h" + +#ifdef USB_HID + +#define CONCAT(low, high) ((high << 8) | low) +#define SIZE_VALUE 0x01 +/* HID main items (HID1_11.pdf, page 38) */ +#define INPUT (0x80 | SIZE_VALUE) +#define OUTPUT (0x90 | SIZE_VALUE) +#define FEATURE (0xb0 | SIZE_VALUE) +#define COLLECTION (0xa0 | SIZE_VALUE) +#define COLLECTION_APPLICATION CONCAT(COLLECTION, 0x01) +#define END_COLLECTION 0xc0 +/* HID global items (HID1_11.pdf, page 45) */ +#define USAGE_PAGE (0x04 | SIZE_VALUE) +#define LOGICAL_MINIMUM (0x14 | SIZE_VALUE) +#define LOGICAL_MAXIMUM (0x24 | SIZE_VALUE) +#define PHYSICAL_MINIMUM (0x34 | SIZE_VALUE) +#define PHYSICAL_MAXIMUM (0x44 | SIZE_VALUE) +#define UNIT_EXPONENT (0x54 | SIZE_VALUE) +#define UNIT (0x64 | SIZE_VALUE) +#define REPORT_SIZE (0x74 | SIZE_VALUE) +#define REPORT_ID (0x84 | SIZE_VALUE) +#define REPORT_COUNT (0x94 | SIZE_VALUE) +#define PUSH (0xa4 | SIZE_VALUE) +#define POP (0xb4 | SIZE_VALUE) +/* Hut1_12.pdf, Table 1, page 14 */ +#define USAGE_PAGE_CONSUMER CONCAT(USAGE_PAGE, 0x0c) +/* Hut1_12.pdf, Table 17, page 77 */ +#define CONSUMER_USAGE 0x09 +#define CONSUMER_USAGE_CONTROL CONCAT(CONSUMER_USAGE, 0x01) +#define CONSUMER_USAGE_MUTE CONCAT(CONSUMER_USAGE, 0xe2) +#define CONSUMER_USAGE_VOLUME_INCREMENT CONCAT(CONSUMER_USAGE, 0xe9) +#define CONSUMER_USAGE_VOLUME_DECREMENT CONCAT(CONSUMER_USAGE, 0xea) +/* Hut1_12.pdf, Table 4, page 20 */ +#define CONSUMER_CONTROL CONCAT(COLLECTION_APPLICATION, 0x01) + +#define USB_DT_HID 0x21 +#define USB_DT_REPORT 0x22 +#define USB_DT_PHYSICAL_DESCRIPTOR 0x23 + +/* serial interface */ +static struct usb_interface_descriptor __attribute__((aligned(2))) + interface_descriptor = +{ + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_HID, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0 +}; + +/* USB_DT_HID: Endpoint descriptor */ +struct usb_hid_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wBcdHID; + uint8_t bCountryCode; + uint8_t bNumDescriptors; + uint8_t bDescriptorType0; + uint16_t wDescriptorLength0; +} __attribute__ ((packed)); + +/* USB_DT_REPORT: Endpoint descriptor */ +static struct usb_hid_descriptor __attribute__((aligned(2))) hid_descriptor = +{ + .bLength = sizeof(struct usb_hid_descriptor), + .bDescriptorType = USB_DT_HID, + .wBcdHID = 0x0100, + .bCountryCode = 0, + .bNumDescriptors = 1, + .bDescriptorType0 = 0x22, + .wDescriptorLength0 = 0 +}; + +static struct usb_endpoint_descriptor __attribute__((aligned(2))) endpoint_descriptor = +{ + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = 0, + .bInterval = 0 +}; + +/* USB_DT_REPORT: Endpoint descriptor */ +struct usb_report_descriptor { + uint16_t wUsagePage; + uint16_t wUsage; + uint16_t wCollection; + uint16_t wCollectionItems[12]; + uint8_t wEndCollection; +} __attribute__ ((packed)); + +static struct usb_report_descriptor __attribute__((aligned(2))) report_descriptor = +{ + .wUsagePage = USAGE_PAGE_CONSUMER, + .wUsage = CONSUMER_USAGE_CONTROL, + .wCollection = COLLECTION_APPLICATION, + .wCollectionItems = { + CONCAT(LOGICAL_MINIMUM, 0x0), + CONCAT(LOGICAL_MAXIMUM, 0x1), + USAGE_PAGE_CONSUMER, + CONSUMER_USAGE_MUTE, + CONSUMER_USAGE_VOLUME_INCREMENT, + CONSUMER_USAGE_VOLUME_DECREMENT, + CONCAT(REPORT_COUNT, 0x3), + CONCAT(REPORT_SIZE, 0x1), + CONCAT(INPUT, 0x42), + CONCAT(REPORT_COUNT, 0x5), + CONCAT(REPORT_SIZE, 0x1), + CONCAT(INPUT, 0x01) + }, + .wEndCollection = END_COLLECTION +}; + +static int ep_in; +static int usb_interface; + +int usb_hid_request_endpoints(struct usb_class_driver *drv) +{ + ep_in = usb_core_request_endpoint(USB_DIR_IN, drv); + if (ep_in < 0) + return -1; + + return 0; +} + +int usb_hid_set_first_interface(int interface) +{ + usb_interface = interface; + + return interface + 1; +} + + +int usb_hid_get_config_descriptor(unsigned char *dest,int max_packet_size) +{ + unsigned char *orig_dest = dest; + + logf("hid: config desc."); + interface_descriptor.bInterfaceNumber = usb_interface; + PACK_DESCRIPTOR(dest, interface_descriptor); + + hid_descriptor.wDescriptorLength0 = sizeof(report_descriptor); + PACK_DESCRIPTOR(dest, hid_descriptor); + + /* Ignore max_packet_size and set to 1 bytes long packet size */ + (void)max_packet_size; + endpoint_descriptor.wMaxPacketSize = 1; + endpoint_descriptor.bInterval = 8; + + endpoint_descriptor.bEndpointAddress = ep_in; + PACK_DESCRIPTOR(dest, endpoint_descriptor); + + return (dest - orig_dest); +} + +/* HID-only class specific requests */ +#define USB_HID_GET_REPORT 0x01 +#define USB_HID_GET_IDLE 0x02 +#define USB_HID_GET_PROTOCOL 0x03 +#define USB_HID_SET_REPORT 0x09 +#define USB_HID_SET_IDLE 0x0a +#define USB_HID_SET_PROTOCOL 0x0b + +/* called by usb_core_control_request() */ +bool usb_hid_control_request(struct usb_ctrlrequest* req, unsigned char* dest) +{ + bool handled = false; + + switch(req->bRequestType & USB_TYPE_MASK) { + case USB_TYPE_STANDARD: { + switch(req->wValue>>8) { /* type */ + case USB_DT_REPORT: { + logf("hid: report"); + if (dest == NULL) { + logf("dest is NULL!"); + } + if (dest) { + unsigned char *orig_dest = dest; + PACK_DESCRIPTOR(dest, report_descriptor); + if(usb_drv_send(EP_CONTROL, orig_dest, dest - orig_dest)) + break; + usb_core_ack_control(req); + + } + handled = true; + break; + } + default: + logf("hid: unsup. std. req"); + break; + } + break; + } + + case USB_TYPE_CLASS: { + switch (req->bRequest) { + case USB_HID_SET_IDLE: + logf("hid: set idle"); + usb_core_ack_control(req); + handled = true; + break; + default: + //logf("hid: unsup. cls. req"); + logf("%d: unsup. cls. req", req->bRequest); + break; + } + break; + } + + case USB_TYPE_VENDOR: + logf("hid: unsup. ven. req"); + break; + } + return handled; +} + +void usb_hid_init_connection(void) +{ + logf("hid: init connection"); +} + +/* called by usb_code_init() */ +void usb_hid_init(void) +{ + logf("hid: init"); +} + +void usb_hid_disconnect(void) +{ + logf("hid: disconnect"); +} + +void usb_hid_send(unsigned char *data, int length) +{ + (void)data; + (void)(length); + + logf("hid: send %d bytes: \"%s\"", length, data); +} + +/* called by usb_core_transfer_complete() */ +void usb_hid_transfer_complete(int ep,int dir, int status, int length) +{ + (void)ep; + (void)dir; + (void)status; + (void)length; + + logf("hid: transfer complete. ep %d, dir %d, status %d ,length %d", + ep, dir, status, length); +} + +#endif /*USB_HID*/ Index: firmware/SOURCES =================================================================== --- firmware/SOURCES (revision 20720) +++ firmware/SOURCES (working copy) @@ -260,6 +260,7 @@ usbstack/usb_storage.c usbstack/usb_serial.c usbstack/usb_charging_only.c +usbstack/usb_hid.c #if CONFIG_USBOTG == USBOTG_ARC target/arm/usb-drv-arc.c #elif CONFIG_USBOTG == USBOTG_ISP1583 Index: firmware/target/arm/usb-drv-arc.c =================================================================== --- firmware/target/arm/usb-drv-arc.c (revision 20720) +++ firmware/target/arm/usb-drv-arc.c (working copy) @@ -394,7 +394,7 @@ while (REG_USBCMD & USBCMD_CTRL_RESET); #if CONFIG_CPU == PP5022 || CONFIG_CPU == PP5024 - /* On a CPU which identifies as a PP5022, this + /* On a CPU which identifies as a PP5022, this initialization must be done after USB is reset. */ outl(inl(0x70000060) | 0xF, 0x70000060); @@ -678,7 +678,7 @@ } */ qh->status = 0; - qh->wait = wait; + qh->wait = wait; new_td=&td_array[pipe*NUM_TDS_PER_EP]; cur_td=new_td; @@ -694,7 +694,7 @@ cur_td++; len-=tdlen; } - while(len>0 ); + while(len>0); //logf("starting ep %d %s",endpoint,send?"send":"receive"); qh->dtd.next_td_ptr = (unsigned int)new_td; @@ -724,7 +724,7 @@ } if (!(REG_ENDPTSTATUS & mask)) { - logf("no prime! %d %d %x", endpoint, pipe, qh->dtd.size_ioc_sts & 0xff ); + logf("no prime! %d %d %x", endpoint, pipe, qh->dtd.size_ioc_sts & 0xff); rc = -3; goto pt_error; } @@ -784,9 +784,9 @@ { int i, bit; - bit=(dir & USB_DIR_IN)? 2:1; + bit=(dir & USB_DIR_IN)? 0x2:0x1; - for (i=1; i < USB_NUM_ENDPOINTS; i++) { + for (i=1;ireserved & DTD_RESERVED_LENGTH_MASK) - + length += ((td->reserved & DTD_RESERVED_LENGTH_MASK) - ((td->size_ioc_sts & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS)); td=(struct transfer_descriptor*) td->next_td_ptr; } @@ -890,7 +890,7 @@ REG_ENDPTSETUPSTAT = REG_ENDPTSETUPSTAT; REG_ENDPTCOMPLETE = REG_ENDPTCOMPLETE; - for (i=0; i<100; i++) { + for (i=0;i<100;i++) { if (!REG_ENDPTPRIME) break; @@ -906,7 +906,7 @@ } usb_drv_cancel_all_transfers(); - + if (!(REG_PORTSC1 & PORTSCX_PORT_RESET)) { logf("usb: slow reset!"); } Index: firmware/usb.c =================================================================== --- firmware/usb.c (revision 20720) +++ firmware/usb.c (working copy) @@ -42,7 +42,7 @@ #ifdef HAVE_USBSTACK #include "usb_core.h" #endif -#include "logf.h" +#include "logf.h" #include "screendump.h" /* Conditions under which we want the entire driver */ @@ -162,7 +162,7 @@ static inline void usb_slave_mode(bool on) { int rc; - + if(on) { DEBUGF("Entering USB slave mode\n"); @@ -180,13 +180,13 @@ /* Let the ISDx00 settle */ sleep(HZ*1); - + usb_enable(false); rc = storage_init(); if(rc) panicf("storage: %d",rc); - + rc = disk_mount_all(); if (rc <= 0) /* no partition */ panicf("mount: %d",rc); @@ -272,10 +272,10 @@ #ifdef HAVE_USBSTACK #ifdef USB_STORAGE usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, false); -#endif +#endif #ifdef USB_CHARGING_ONLY usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, true); -#endif +#endif usb_attach(); #endif break; @@ -290,10 +290,10 @@ #endif #ifdef USB_STORAGE usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, true); -#endif +#endif #ifdef USB_CHARGING_ONLY usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, false); -#endif +#endif /* Check any drivers enabled at this point for exclusive storage * access requirements. */ @@ -493,7 +493,7 @@ #endif /* USB_FIREWIRE_HANDLING */ current_status = usb_detect(); - + /* Only report when the status has changed */ if(current_status != last_usb_status) { @@ -561,7 +561,7 @@ usb_enable(false); queue_init(&usb_queue, true); - + usb_thread_entry = create_thread(usb_thread, usb_stack, sizeof(usb_stack), 0, usb_thread_name IF_PRIO(, PRIORITY_SYSTEM) IF_COP(, CPU));