1/* sane - Scanner Access Now Easy.
2
3   Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
4
5   This file is part of the SANE package.
6
7   This program is free software; you can redistribute it and/or
8   modify it under the terms of the GNU General Public License as
9   published by the Free Software Foundation; either version 2 of the
10   License, or (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program.  If not, see <https://www.gnu.org/licenses/>.
19*/
20
21#define DEBUG_DECLARE_ONLY
22
23#include "usb_device.h"
24
25namespace genesys {
26
27IUsbDevice::~IUsbDevice() = default;
28
29UsbDevice::~UsbDevice()
30{
31    if (is_open()) {
32        DBG(DBG_error, "UsbDevice not closed; closing automatically");
33        close();
34    }
35}
36
37void UsbDevice::open(const char* dev_name)
38{
39    DBG_HELPER(dbg);
40
41    if (is_open()) {
42        throw SaneException("device already open");
43    }
44    int device_num = 0;
45
46    dbg.status("open device");
47    TIE(sanei_usb_open(dev_name, &device_num));
48
49    name_ = dev_name;
50    device_num_ = device_num;
51    is_open_ = true;
52}
53
54void UsbDevice::clear_halt()
55{
56    DBG_HELPER(dbg);
57    assert_is_open();
58    TIE(sanei_usb_clear_halt(device_num_));
59}
60
61void UsbDevice::reset()
62{
63    DBG_HELPER(dbg);
64    assert_is_open();
65    TIE(sanei_usb_reset(device_num_));
66}
67
68void UsbDevice::close()
69{
70    DBG_HELPER(dbg);
71    assert_is_open();
72
73    // we can't do much if closing fails, so we close the device on our side regardless of the
74    // function succeeds
75    int device_num = device_num_;
76
77    set_not_open();
78    sanei_usb_close(device_num);
79}
80
81std::uint16_t UsbDevice::get_vendor_id()
82{
83    DBG_HELPER(dbg);
84    assert_is_open();
85    int vendor = 0;
86    int product = 0;
87    TIE(sanei_usb_get_vendor_product(device_num_, &vendor, &product));
88    return static_cast<std::uint16_t>(vendor);
89}
90
91std::uint16_t UsbDevice::get_product_id()
92{
93    DBG_HELPER(dbg);
94    assert_is_open();
95    int vendor = 0;
96    int product = 0;
97    TIE(sanei_usb_get_vendor_product(device_num_, &vendor, &product));
98    return static_cast<std::uint16_t>(product);
99}
100
101std::uint16_t UsbDevice::get_bcd_device()
102{
103    DBG_HELPER(dbg);
104    assert_is_open();
105    sanei_usb_dev_descriptor desc;
106    TIE(sanei_usb_get_descriptor(device_num_, &desc));
107    return desc.bcd_dev;
108}
109
110void UsbDevice::control_msg(int rtype, int reg, int value, int index, int length,
111                            std::uint8_t* data)
112{
113    DBG_HELPER(dbg);
114    assert_is_open();
115    TIE(sanei_usb_control_msg(device_num_, rtype, reg, value, index, length, data));
116}
117
118void UsbDevice::bulk_read(std::uint8_t* buffer, std::size_t* size)
119{
120    DBG_HELPER(dbg);
121    assert_is_open();
122    TIE(sanei_usb_read_bulk(device_num_, buffer, size));
123}
124
125void UsbDevice::bulk_write(const std::uint8_t* buffer, std::size_t* size)
126{
127    DBG_HELPER(dbg);
128    assert_is_open();
129    TIE(sanei_usb_write_bulk(device_num_, buffer, size));
130}
131
132void UsbDevice::assert_is_open() const
133{
134    if (!is_open()) {
135        throw SaneException("device not open");
136    }
137}
138
139void UsbDevice::set_not_open()
140{
141    device_num_ = 0;
142    is_open_ = false;
143    name_ = "";
144}
145
146} // namespace genesys
147