summaryrefslogtreecommitdiffstats
path: root/utils/hwstub/lib
diff options
context:
space:
mode:
Diffstat (limited to 'utils/hwstub/lib')
-rw-r--r--utils/hwstub/lib/hwstub.cpp46
-rw-r--r--utils/hwstub/lib/hwstub_net.cpp12
-rw-r--r--utils/hwstub/lib/hwstub_usb.cpp52
-rw-r--r--utils/hwstub/lib/hwstub_virtual.cpp12
4 files changed, 122 insertions, 0 deletions
diff --git a/utils/hwstub/lib/hwstub.cpp b/utils/hwstub/lib/hwstub.cpp
index 9dd2915903..5e708c3bb8 100644
--- a/utils/hwstub/lib/hwstub.cpp
+++ b/utils/hwstub/lib/hwstub.cpp
@@ -45,6 +45,8 @@ std::string error_string(error err)
case error::PROTOCOL_ERROR: return "network protocol error";
case error::TIMEOUT: return "timeout";
case error::OVERFLW: return "overflow";
+ case error::UNIMPLEMENTED: return "operation is not implemented";
+ case error::UNSUPPORTED: return "operation unsupported";
default: return "unknown error";
}
}
@@ -457,6 +459,38 @@ error handle::write(uint32_t addr, const void *buf, size_t& sz, bool atomic)
return error::SUCCESS;
}
+error handle::cop_op(uint8_t op, uint8_t args[HWSTUB_COP_ARGS], const void *out_data,
+ size_t out_size, void *in_data, size_t *in_size)
+{
+ std::unique_lock<std::recursive_mutex> lock(m_mutex);
+ /* get a pointer so that it's not destroyed during the runtime of the function,
+ * the pointer will be released at the end of the function */
+ std::shared_ptr<context> ctx = m_dev->get_context();
+ if(!ctx)
+ return error::NO_CONTEXT;
+ /* ensure valid status */
+ error err = status();
+ if(err != error::SUCCESS)
+ return err;
+ return cop_dev(op, args, out_data, out_size, in_data, in_size);
+}
+
+error handle::read32_cop(uint8_t args[HWSTUB_COP_ARGS], uint32_t& value)
+{
+ size_t sz = sizeof(value);
+ error err = cop_op(HWSTUB_COP_READ, args, nullptr, 0, &value, &sz);
+ if(err != error::SUCCESS)
+ return err;
+ if(sz != sizeof(value))
+ return error::ERROR;
+ return error::SUCCESS;
+}
+
+error handle::write32_cop(uint8_t args[HWSTUB_COP_ARGS], uint32_t value)
+{
+ return cop_op(HWSTUB_COP_WRITE, args, &value, sizeof(value), nullptr, nullptr);
+}
+
error handle::status() const
{
/* check context */
@@ -616,6 +650,18 @@ error dummy_handle::exec_dev(uint32_t addr, uint16_t flags)
return error::DUMMY;
}
+error dummy_handle::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)
+{
+ (void) op;
+ (void) args;
+ (void) out_data;
+ (void) out_size;
+ (void) in_data;
+ (void) in_size;
+ return error::DUMMY;
+}
+
error dummy_handle::status() const
{
error err = handle::status();
diff --git a/utils/hwstub/lib/hwstub_net.cpp b/utils/hwstub/lib/hwstub_net.cpp
index ddafea6351..c9d201a761 100644
--- a/utils/hwstub/lib/hwstub_net.cpp
+++ b/utils/hwstub/lib/hwstub_net.cpp
@@ -735,6 +735,18 @@ error handle::exec_dev(uint32_t addr, uint16_t flags)
return error::SUCCESS;
}
+error handle::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)
+{
+ (void) op;
+ (void) args;
+ (void) out_data;
+ (void) out_size;
+ (void) in_data;
+ (void) in_size;
+ return error::UNIMPLEMENTED;
+}
+
error handle::status() const
{
return hwstub::handle::status();
diff --git a/utils/hwstub/lib/hwstub_usb.cpp b/utils/hwstub/lib/hwstub_usb.cpp
index 6bb1cfa049..37249f5812 100644
--- a/utils/hwstub/lib/hwstub_usb.cpp
+++ b/utils/hwstub/lib/hwstub_usb.cpp
@@ -399,6 +399,46 @@ error rb_handle::write_dev(uint32_t addr, const void *buf, size_t& sz, bool atom
return ret;
}
+error rb_handle::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)
+{
+ (void) op;
+ (void) args;
+ (void) out_data;
+ (void) out_size;
+ (void) in_data;
+ (void) in_size;
+ std::shared_ptr<hwstub::context> hctx = get_device()->get_context();
+ if(!hctx)
+ return error::NO_CONTEXT;
+
+ /* construct out request: header followed by (optional) data */
+ size_t hdr_sz = sizeof(struct hwstub_cop_req_t);
+ uint8_t *tmp_buf = new uint8_t[out_size + hdr_sz];
+ struct hwstub_cop_req_t *req = reinterpret_cast<struct hwstub_cop_req_t *>(tmp_buf);
+ req->bOp = op;
+ for(int i = 0; i < HWSTUB_COP_ARGS; i++)
+ req->bArgs[i] = args[i];
+ if(out_size > 0)
+ memcpy(tmp_buf + hdr_sz, out_data, out_size);
+ error ret = interpret_libusb_error(libusb_control_transfer(m_handle,
+ LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
+ HWSTUB_COPROCESSOR_OP, m_transac_id++, m_intf,
+ (unsigned char *)req, out_size + hdr_sz, m_timeout), out_size + hdr_sz);
+ delete[] tmp_buf;
+ /* return errors if any */
+ if(ret != error::SUCCESS)
+ return ret;
+ /* return now if there is no read stage */
+ if(in_data == nullptr)
+ return error::SUCCESS;
+ /* perform read stage (use the same transaction ID) */
+ return interpret_libusb_size(libusb_control_transfer(m_handle,
+ LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN,
+ HWSTUB_READ2, m_transac_id - 1, m_intf,
+ (unsigned char *)in_data, *in_size, m_timeout), *in_size);
+}
+
bool rb_handle::find_intf(struct libusb_device_descriptor *dev,
struct libusb_config_descriptor *config, int& intf_idx)
{
@@ -674,6 +714,18 @@ error jz_handle::write_dev(uint32_t addr, const void *buf, size_t& sz, bool atom
return ret;
}
+error jz_handle::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)
+{
+ (void) op;
+ (void) args;
+ (void) out_data;
+ (void) out_size;
+ (void) in_data;
+ (void) in_size;
+ return error::UNSUPPORTED;
+}
+
bool jz_handle::is_boot_dev(struct libusb_device_descriptor *dev,
struct libusb_config_descriptor *config)
{
diff --git a/utils/hwstub/lib/hwstub_virtual.cpp b/utils/hwstub/lib/hwstub_virtual.cpp
index fada56fb83..5c9e79e5a1 100644
--- a/utils/hwstub/lib/hwstub_virtual.cpp
+++ b/utils/hwstub/lib/hwstub_virtual.cpp
@@ -221,6 +221,18 @@ error handle::exec_dev(uint32_t addr, uint16_t flags)
return p ? p->exec_dev(addr, flags) : error::DISCONNECTED;
}
+error handle::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)
+{
+ (void) op;
+ (void) args;
+ (void) out_data;
+ (void) out_size;
+ (void) in_data;
+ (void) in_size;
+ return error::UNSUPPORTED;
+}
+
error handle::status() const
{
return hwstub::handle::status();