eadba57d53
libusb limits control transfer sizes to 4k, see diff for details. Change-Id: Id2e638010274009ea641d06e9040a8b9ab9d54a9
202 lines
7.3 KiB
C++
202 lines
7.3 KiB
C++
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2015 by Amaury Pouly
|
|
*
|
|
* 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 __HWSTUB_USB_HPP__
|
|
#define __HWSTUB_USB_HPP__
|
|
|
|
#include "hwstub_usb.hpp"
|
|
#include <libusb.h>
|
|
|
|
namespace hwstub {
|
|
namespace usb {
|
|
|
|
/** USB context
|
|
*
|
|
* Context based on libusb. */
|
|
class context : public hwstub::context
|
|
{
|
|
protected:
|
|
context(libusb_context *ctx, bool cleanup_ctx);
|
|
public:
|
|
virtual ~context();
|
|
/** Return native libusb context */
|
|
libusb_context *native_context();
|
|
/** Create a USB context. If cleanup_ctx is true, libusb_exit() will be
|
|
* called on the context on deletion of this class. If ctx is NULL, libusb_init()
|
|
* will be called with NULL so there is no need to init the default context. */
|
|
static std::shared_ptr<context> create(libusb_context *ctx, bool cleanup_ctx = false,
|
|
std::string *error = nullptr);
|
|
|
|
protected:
|
|
/* NOTE ctx_dev_t = libusb_device* */
|
|
libusb_device *from_ctx_dev(ctx_dev_t dev);
|
|
ctx_dev_t to_ctx_dev(libusb_device *dev);
|
|
virtual error fetch_device_list(std::vector<ctx_dev_t>& list, void*& ptr);
|
|
virtual void destroy_device_list(void *ptr);
|
|
virtual error create_device(ctx_dev_t dev, std::shared_ptr<hwstub::device>& hwdev);
|
|
virtual bool match_device(ctx_dev_t dev, std::shared_ptr<hwstub::device> hwdev);
|
|
|
|
libusb_context *m_usb_ctx; /* libusb context (might be NULL) */
|
|
bool m_cleanup_ctx; /* cleanup context on delete ? */
|
|
};
|
|
|
|
/** USB device
|
|
*
|
|
* Device based on libusb_device. */
|
|
class device : public hwstub::device
|
|
{
|
|
friend class context; /* for ctor */
|
|
protected:
|
|
device(std::shared_ptr<hwstub::context> ctx, libusb_device *dev);
|
|
public:
|
|
virtual ~device();
|
|
/** Return native libusb device */
|
|
libusb_device *native_device();
|
|
/** Get bus number */
|
|
uint8_t get_bus_number();
|
|
/** Get device address */
|
|
uint8_t get_address();
|
|
/** Get device VID */
|
|
uint16_t get_vid();
|
|
/** Get device PID */
|
|
uint16_t get_pid();
|
|
|
|
protected:
|
|
/** Return true if this might be a hwstub device and should appear in the list */
|
|
static bool is_hwstub_dev(libusb_device *dev);
|
|
|
|
virtual error open_dev(std::shared_ptr<hwstub::handle>& handle);
|
|
virtual bool has_multiple_open() const;
|
|
|
|
libusb_device *m_dev; /* USB device */
|
|
};
|
|
|
|
/** USB handle
|
|
*
|
|
* Handle based on libusb_device_handle. */
|
|
class handle : public hwstub::handle
|
|
{
|
|
protected:
|
|
handle(std::shared_ptr<hwstub::device> dev, libusb_device_handle *handle);
|
|
public:
|
|
virtual ~handle();
|
|
/** set operation timeout */
|
|
void set_timeout(std::chrono::milliseconds ms);
|
|
|
|
protected:
|
|
/* return the maximum size of a libusb control transfer, this is a "known"
|
|
* limitation that is completely undocumented (sigh) and applies at least
|
|
* to linux and windows hosts */
|
|
size_t max_libusb_control_xfer_size() const;
|
|
/* interpret libusb error: >=0 means SUCCESS, others are treated as errors,
|
|
* LIBUSB_ERROR_NO_DEVICE is treated as DISCONNECTED */
|
|
error interpret_libusb_error(int err);
|
|
/* interpret libusb error: <0 returns interpret_libusb_error(err), otherwise
|
|
* returns SUCCESS if err == expected_value */
|
|
error interpret_libusb_error(int err, size_t expected_value);
|
|
/* interpret libusb error: <0 returns interpret_libusb_error(err), otherwise
|
|
* returns SUCCESS and write size in out_size */
|
|
error interpret_libusb_size(int err, size_t& out_size);
|
|
|
|
libusb_device_handle *m_handle; /* USB handle */
|
|
unsigned int m_timeout; /* in milliseconds */
|
|
};
|
|
|
|
/** Rockbox USB handle
|
|
*
|
|
* HWSTUB/Rockbox protocol. */
|
|
class rb_handle : public handle
|
|
{
|
|
friend class device; /* for find_intf() */
|
|
protected:
|
|
rb_handle(std::shared_ptr<hwstub::device> dev, libusb_device_handle *handle, int intf);
|
|
public:
|
|
virtual ~rb_handle();
|
|
|
|
protected:
|
|
virtual error read_dev(uint32_t addr, void *buf, size_t& sz, bool atomic);
|
|
virtual error write_dev(uint32_t addr, const void *buf, size_t& sz, bool atomic);
|
|
virtual error get_dev_desc(uint16_t desc, void *buf, size_t& buf_sz);
|
|
virtual error get_dev_log(void *buf, size_t& buf_sz);
|
|
virtual error exec_dev(uint32_t addr, uint16_t flags);
|
|
virtual error cop_dev(uint8_t op, uint8_t args[HWSTUB_COP_ARGS], const void *out_data,
|
|
size_t out_size, void *in_data, size_t *in_size);
|
|
virtual error status() const;
|
|
virtual size_t get_buffer_size();
|
|
/* Probe a device to check if it is an hwstub device and return the interface
|
|
* number, or <0 on error. */
|
|
static bool find_intf(struct libusb_device_descriptor *dev,
|
|
struct libusb_config_descriptor *config, int& intf);
|
|
|
|
error m_probe_status; /* probing status */
|
|
int m_intf; /* interface number */
|
|
uint16_t m_transac_id; /* transaction ID */
|
|
size_t m_buf_size; /* Device buffer size */
|
|
};
|
|
|
|
/** JZ USB handle
|
|
*
|
|
* JZ boot protocol */
|
|
class jz_handle : public handle
|
|
{
|
|
friend class device; /* for is_boot_dev() */
|
|
protected:
|
|
jz_handle(std::shared_ptr<hwstub::device> dev, libusb_device_handle *handle);
|
|
public:
|
|
virtual ~jz_handle();
|
|
|
|
protected:
|
|
virtual error read_dev(uint32_t addr, void *buf, size_t& sz, bool atomic);
|
|
virtual error write_dev(uint32_t addr, const void *buf, size_t& sz, bool atomic);
|
|
virtual error get_dev_desc(uint16_t desc, void *buf, size_t& buf_sz);
|
|
virtual error get_dev_log(void *buf, size_t& buf_sz);
|
|
virtual error exec_dev(uint32_t addr, uint16_t flags);
|
|
virtual error cop_dev(uint8_t op, uint8_t args[HWSTUB_COP_ARGS], const void *out_data,
|
|
size_t out_size, void *in_data, size_t *in_size);
|
|
virtual error status() const;
|
|
virtual size_t get_buffer_size();
|
|
error probe();
|
|
error probe_jz4760b();
|
|
error read_reg32(uint32_t addr, uint32_t& value);
|
|
error write_reg32(uint32_t addr, uint32_t value);
|
|
|
|
error jz_cpuinfo(char cpuinfo[8]);
|
|
error jz_set_addr(uint32_t addr);
|
|
error jz_set_length(uint32_t size);
|
|
error jz_upload(void *data, size_t& length);
|
|
error jz_download(const void *data, size_t& length);
|
|
error jz_start1(uint32_t addr);
|
|
error jz_flush_caches();
|
|
error jz_start2(uint32_t addr);
|
|
/* Probe a device to check if it is a jz boot device */
|
|
static bool is_boot_dev(struct libusb_device_descriptor *dev,
|
|
struct libusb_config_descriptor *config);
|
|
|
|
error m_probe_status; /* probing status */
|
|
struct hwstub_version_desc_t m_desc_version;
|
|
struct hwstub_layout_desc_t m_desc_layout;
|
|
struct hwstub_target_desc_t m_desc_target;
|
|
struct hwstub_jz_desc_t m_desc_jz;
|
|
};
|
|
|
|
} // namespace usb
|
|
} // namespace hwstub
|
|
|
|
#endif /* __HWSTUB_USB_HPP__ */
|