blob: 5f83134cdb3ec8aeab44a97fa638360ff367e87c [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "op_commands.h"
#include <arpa/inet.h>
#include <cstring>
#include <base/logging.h>
#include "device_descriptors.h"
#include "smart_buffer.h"
#include "usbip_constants.h"
// These are constants used to describe the exported device. They are used to
// populate the OpRepDevice message used when responding to OpReqDevlist and
// OpReqImport requests.
const char kUsbPath[] = "/sys/devices/pci0000:00/0000:00:01.2/usb1/1-1";
const char kBusId[] = "1-1";
constexpr int kBusnum = 1;
constexpr int kDevnum = 2;
constexpr int kSpeed = 3; // Represents a high-speed USB device.
constexpr uint16_t kUsbipVersion = 0x0111; // usbip version in BCD.
void SetOpHeader(uint16_t command, int status, OpHeader* header) {
header->version = kUsbipVersion;
header->command = command;
header->status = status;
}
void SetOpRepDevlistHeader(uint16_t command, int status, int numExportedDevices,
OpRepDevlistHeader* devlist_header) {
SetOpHeader(command, status, &devlist_header->header);
devlist_header->numExportedDevices = numExportedDevices;
}
void SetOpRepDevice(const UsbDeviceDescriptor& dev_dsc,
const UsbConfigurationDescriptor& config,
OpRepDevice* device) {
// Set constants.
memset(device->usbPath, 0, 256);
strcpy(device->usbPath, kUsbPath);
memset(device->busID, 0, 32);
strcpy(device->busID, kBusId);
device->busnum = kBusnum;
device->devnum = kDevnum;
device->speed = kSpeed;
// Set values using |dev_dsc|.
device->idVendor = dev_dsc.idVendor;
device->idProduct = dev_dsc.idProduct;
device->bcdDevice = dev_dsc.bcdDevice;
device->bDeviceClass = dev_dsc.bDeviceClass;
device->bDeviceSubClass = dev_dsc.bDeviceSubClass;
device->bDeviceProtocol = dev_dsc.bDeviceProtocol;
device->bNumConfigurations = dev_dsc.bNumConfigurations;
// Set values using |config|.
device->bConfigurationValue = config.bConfigurationValue;
device->bNumInterfaces = config.bNumInterfaces;
}
void SetOpRepDevlistInterfaces(
const std::vector<UsbInterfaceDescriptor>& interfaces,
OpRepDevlistInterface** rep_interfaces) {
// TODO(daviev): Change this to use a smart pointer at some point.
*rep_interfaces = (OpRepDevlistInterface*)malloc(
interfaces.size() * sizeof(OpRepDevlistInterface));
for (size_t i = 0; i < interfaces.size(); ++i) {
const auto& interface = interfaces[i];
(*rep_interfaces)[i].bInterfaceClass = interface.bInterfaceClass;
(*rep_interfaces)[i].bInterfaceSubClass = interface.bInterfaceSubClass;
(*rep_interfaces)[i].bInterfaceProtocol = interface.bInterfaceProtocol;
(*rep_interfaces)[i].padding = 0;
}
}
// Creates the OpRepDevlist message used to respond to a request to list the
// host's exported USB devices.
void CreateOpRepDevlist(const UsbDeviceDescriptor& device,
const UsbConfigurationDescriptor& config,
const std::vector<UsbInterfaceDescriptor>& interfaces,
OpRepDevlist* list) {
SetOpRepDevlistHeader(OP_REP_DEVLIST_CMD, 0, 1, &list->header);
SetOpRepDevice(device, config, &list->device);
SetOpRepDevlistInterfaces(interfaces, &list->interfaces);
}
void CreateOpRepImport(const UsbDeviceDescriptor& dev_dsc,
const UsbConfigurationDescriptor& config,
OpRepImport* rep) {
SetOpHeader(OP_REP_IMPORT_CMD, 0, &rep->header);
SetOpRepDevice(dev_dsc, config, &rep->device);
}
SmartBuffer PackOpHeader(OpHeader header) {
header.version = htons(header.version);
header.command = htons(header.command);
header.status = htonl(header.status);
SmartBuffer packed_header(sizeof(header));
packed_header.Add(&header, sizeof(header));
return packed_header;
}
SmartBuffer PackOpRepDevice(OpRepDevice device) {
device.busnum = htonl(device.busnum);
device.devnum = htonl(device.devnum);
device.speed = htonl(device.speed);
device.idVendor = htons(device.idVendor);
device.idProduct = htons(device.idProduct);
device.bcdDevice = htons(device.bcdDevice);
SmartBuffer packed_device(sizeof(device));
packed_device.Add(&device, sizeof(device));
return packed_device;
}
SmartBuffer PackOpRepDevlistHeader(OpRepDevlistHeader devlist_header) {
SmartBuffer packed_op_header = PackOpHeader(devlist_header.header);
devlist_header.numExportedDevices = htonl(devlist_header.numExportedDevices);
SmartBuffer packed_header(sizeof(OpRepDevlistHeader));
packed_header.Add(packed_op_header);
packed_header.Add(&devlist_header.numExportedDevices,
sizeof(devlist_header.numExportedDevices));
return packed_header;
}
SmartBuffer PackOpRepDevlist(OpRepDevlist devlist) {
SmartBuffer packed_header = PackOpRepDevlistHeader(devlist.header);
SmartBuffer packed_device = PackOpRepDevice(devlist.device);
size_t interfaces_size =
sizeof(*devlist.interfaces) * devlist.device.bNumInterfaces;
size_t buffer_size =
sizeof(devlist.header) + sizeof(devlist.device) + interfaces_size;
SmartBuffer packed_devlist(buffer_size);
packed_devlist.Add(packed_header);
packed_devlist.Add(packed_device);
packed_devlist.Add(devlist.interfaces, interfaces_size);
return packed_devlist;
}
SmartBuffer PackOpRepImport(OpRepImport import) {
SmartBuffer packed_header = PackOpHeader(import.header);
SmartBuffer packed_device = PackOpRepDevice(import.device);
SmartBuffer packed_import(sizeof(import));
packed_import.Add(packed_header);
packed_import.Add(packed_device);
return packed_import;
}
void UnpackOpHeader(OpHeader* header) {
header->version = ntohs(header->version);
header->command = ntohs(header->command);
header->status = ntohl(header->status);
}