Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions doc/USB_Linux.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# USB

## LibUSB

libusb - Check Linux/Windows install Guides for this

- On Ubuntu this is likely already installed.

## Permissions

If you are on Linux, you may need to add a UDEV Rule to allow the Printer to be accessed by your User.

Rule: `/etc/udev/rules.d/99-brother-ptp700.rules`

```bash
SUBSYSTEMS=="usb", GROUP="plugdev", ACTION=="add", ATTRS{idVendor}==<VENDOR_ID>, ATTRS{idProduct}==<PRODUCT_ID>, MODE="0660"
```

This sets the owner of the device node to root:usbusers rather than root:root

Ensure that the User is in the `plu gdev` group : `sudo usermod -aG plugdev <USER>`

## Brother P-Touch

Note: If your printer has a 'PLite' mode, you need to disable it if you want to print via USB. Make sure that the corresponding LED is not lit by holding the button down until it turns off.

Get VendorID : `lsusb | grep -i Brother | awk '{print $6}' | cut -d':' -f1`

Get ProductID: `lsusb | grep -i Brother | awk '{print $6}' | cut -d':' -f2`
54 changes: 48 additions & 6 deletions labelprinterkit/backends/usb.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from __future__ import annotations

from time import sleep

import usb.core
Expand All @@ -8,26 +9,67 @@


class PyUSBBackend(BaseBackend):
def __init__(self):
dev = usb.core.find(custom_match=self.is_usb_printer)
"""Assumes only a SINGLE USB Printer / Brother Device is Attached"""

def __init__(self) -> None:
self._dev = PyUSBBackend.get_device()

@staticmethod
def get_device() -> usb.core.Device:
"""Get the PyUSB Device for a USB Printer"""
dev = usb.core.find(custom_match=PyUSBBackend.is_usb_printer)
if dev is None:
raise OSError('Device not found')
self._dev = dev
raise OSError("No Printer Found")
return dev

@staticmethod
def is_usb_printer(dev) -> bool:
"""Check if the Device is a USB Printer - by Device Class or Interface Class"""
if dev.bDeviceClass == 7:
return True
for cfg in dev:
if usb.util.find_descriptor(cfg, bInterfaceClass=7) is not None:
return True
return False

def write(self, data: bytes):
@staticmethod
def is_brother_manufacturer(dev) -> bool:
"""Check if the Device is a Brother Printer - by Manufacturer"""
try:
manufacturer = usb.util.get_string(dev, dev.iManufacturer)
except (usb.core.USBError, ValueError):
manufacturer = None

if manufacturer == "Brother":
return True
return False

def detach_from_kernel(self) -> None:
"""
Detach the given Device from the Kernel - allowing PyUSB Exclusive Access
Required for: usb.core.USBError: [Errno 16] Resource busy
"""
self._dev.reset()

interface = self._dev[0].interfaces()[0].bInterfaceNumber
if self._dev.is_kernel_driver_active(interface):
try:
self._dev.detach_kernel_driver(interface)
except usb.core.USBError:
pass

self._dev.set_configuration()

self.refresh()

def refresh(self) -> None:
self._dev = PyUSBBackend.get_device()

def write(self, data: bytes) -> None:
self._dev.write(0x2, data)

def read(self, count: int) -> bytes | None:
for i in range(0, 3):
for _ in range(0, 3):
data = self._dev.read(0x81, count)
if data:
return data
Expand Down